Remove wrong asserts
[ardour.git] / gtk2_ardour / canvas-waveview.c
index fdcdcd87454c72f4316949f774f5c96721f5cda2..bf7dad04297eb8e788b39e5a30912b881be95132 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-     Copyright (C) 2000-2002 Paul Davis 
+     Copyright (C) 2000-2002 Paul Davis
 
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
 
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
 #include <cairo.h>
 #include <string.h>
 #include <limits.h>
 #include <cairo.h>
 #include <string.h>
 #include <limits.h>
+#include <unistd.h>
 
 
-#include <ardour/dB.h>
+#include "ardour/dB.h"
 
 #include "logmeter.h"
 #include "canvas-waveview.h"
 #include "rgb_macros.h"
 
 
 #include "logmeter.h"
 #include "canvas-waveview.h"
 #include "rgb_macros.h"
 
+/* POSIX guarantees casting between void* and function pointers, ISO C doesn't
+ * We can work around warnings by going one step deeper in our casts
+ */
+#if defined(_POSIX_VERSION) || defined(COMPILER_MINGW)
+#define POSIX_FUNC_PTR_CAST(type, object) *((type*) &(object))
+#endif // _POSIX_VERSION
 
 
-extern void c_stacktrace();
+extern void c_stacktrace(void);
 
 enum {
         PROP_0,
 
 enum {
         PROP_0,
@@ -114,6 +121,9 @@ static guint32 gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview
                                                   gulong               start_sample,
                                                   gulong               end_sample);
 
                                                   gulong               start_sample,
                                                   gulong               end_sample);
 
+
+static int _gradient_rendering = 0;
+
 static GnomeCanvasItemClass *parent_class;
 
 GType
 static GnomeCanvasItemClass *parent_class;
 
 GType
@@ -163,106 +173,106 @@ gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
                  PROP_DATA_SRC,
                  g_param_spec_pointer ("data_src", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
                  PROP_DATA_SRC,
                  g_param_spec_pointer ("data_src", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_CHANNEL,
                  g_param_spec_uint ("channel", NULL, NULL,
                                     0, G_MAXUINT, 0,
                                     (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_CHANNEL,
                  g_param_spec_uint ("channel", NULL, NULL,
                                     0, G_MAXUINT, 0,
                                     (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_LENGTH_FUNCTION,
                  g_param_spec_pointer ("length_function", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_LENGTH_FUNCTION,
                  g_param_spec_pointer ("length_function", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_SOURCEFILE_LENGTH_FUNCTION,
                  g_param_spec_pointer ("sourcefile_length_function", NULL, NULL,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_SOURCEFILE_LENGTH_FUNCTION,
                  g_param_spec_pointer ("sourcefile_length_function", NULL, NULL,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_PEAK_FUNCTION,
                  g_param_spec_pointer ("peak_function", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_PEAK_FUNCTION,
                  g_param_spec_pointer ("peak_function", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_GAIN_FUNCTION,
                  g_param_spec_pointer ("gain_function", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_GAIN_FUNCTION,
                  g_param_spec_pointer ("gain_function", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_GAIN_SRC,
                  g_param_spec_pointer ("gain_src", NULL, NULL,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_GAIN_SRC,
                  g_param_spec_pointer ("gain_src", NULL, NULL,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-       
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_CACHE,
                  g_param_spec_pointer ("cache", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_CACHE,
                  g_param_spec_pointer ("cache", NULL, NULL,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_CACHE_UPDATER,
                  g_param_spec_boolean ("cache_updater", NULL, NULL,
                                       FALSE,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_CACHE_UPDATER,
                  g_param_spec_boolean ("cache_updater", NULL, NULL,
                                       FALSE,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_SAMPLES_PER_UNIT,
                  g_param_spec_double ("samples_per_unit", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_SAMPLES_PER_UNIT,
                  g_param_spec_double ("samples_per_unit", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_AMPLITUDE_ABOVE_AXIS,
                  g_param_spec_double ("amplitude_above_axis", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_AMPLITUDE_ABOVE_AXIS,
                  g_param_spec_double ("amplitude_above_axis", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_X,
                  g_param_spec_double ("x", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_X,
                  g_param_spec_double ("x", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_Y,
                  g_param_spec_double ("y", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_Y,
                  g_param_spec_double ("y", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_HEIGHT,
                  g_param_spec_double ("height", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_HEIGHT,
                  g_param_spec_double ("height", NULL, NULL,
                                       0.0, G_MAXDOUBLE, 0.0,
                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_WAVE_COLOR,
                  g_param_spec_uint ("wave_color", NULL, NULL,
                                     0, G_MAXUINT, 0,
                                     (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_WAVE_COLOR,
                  g_param_spec_uint ("wave_color", NULL, NULL,
                                     0, G_MAXUINT, 0,
                                     (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_CLIP_COLOR,
                  g_param_spec_uint ("clip_color", NULL, NULL,
                                     0, G_MAXUINT, 0,
                                     (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_CLIP_COLOR,
                  g_param_spec_uint ("clip_color", NULL, NULL,
                                     0, G_MAXUINT, 0,
                                     (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_ZERO_COLOR,
         g_object_class_install_property
                 (gobject_class,
                  PROP_ZERO_COLOR,
@@ -283,7 +293,7 @@ gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
                  g_param_spec_boolean ("filled", NULL, NULL,
                                        FALSE,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
                  g_param_spec_boolean ("filled", NULL, NULL,
                                        FALSE,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_RECTIFIED,
         g_object_class_install_property
                 (gobject_class,
                  PROP_RECTIFIED,
@@ -304,16 +314,16 @@ gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
                  g_param_spec_boolean ("logscaled", NULL, NULL,
                                        FALSE,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
                  g_param_spec_boolean ("logscaled", NULL, NULL,
                                        FALSE,
                                        (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         g_object_class_install_property
                 (gobject_class,
                  PROP_REGION_START,
                  g_param_spec_uint ("region_start", NULL, NULL,
                                     0, G_MAXUINT, 0,
                                     (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property
                 (gobject_class,
                  PROP_REGION_START,
                  g_param_spec_uint ("region_start", NULL, NULL,
                                     0, G_MAXUINT, 0,
                                     (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-        
+
         object_class->destroy = gnome_canvas_waveview_destroy;
         object_class->destroy = gnome_canvas_waveview_destroy;
-        
+
         item_class->update = gnome_canvas_waveview_update;
         item_class->bounds = gnome_canvas_waveview_bounds;
         item_class->point = gnome_canvas_waveview_point;
         item_class->update = gnome_canvas_waveview_update;
         item_class->bounds = gnome_canvas_waveview_bounds;
         item_class->point = gnome_canvas_waveview_point;
@@ -321,8 +331,14 @@ gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
         item_class->draw = gnome_canvas_waveview_draw;
 }
 
         item_class->draw = gnome_canvas_waveview_draw;
 }
 
+void
+gnome_canvas_waveview_set_gradient_waveforms (int yn)
+{
+       _gradient_rendering = yn;
+}
+
 GnomeCanvasWaveViewCache*
 GnomeCanvasWaveViewCache*
-gnome_canvas_waveview_cache_new ()
+gnome_canvas_waveview_cache_new (void)
 {
        GnomeCanvasWaveViewCache *c;
 
 {
        GnomeCanvasWaveViewCache *c;
 
@@ -378,13 +394,9 @@ gnome_canvas_waveview_init (GnomeCanvasWaveView *waveview)
 static void
 gnome_canvas_waveview_destroy (GtkObject *object)
 {
 static void
 gnome_canvas_waveview_destroy (GtkObject *object)
 {
-       GnomeCanvasWaveView *waveview;
-
        g_return_if_fail (object != NULL);
        g_return_if_fail (GNOME_IS_CANVAS_WAVEVIEW (object));
 
        g_return_if_fail (object != NULL);
        g_return_if_fail (GNOME_IS_CANVAS_WAVEVIEW (object));
 
-       waveview = GNOME_CANVAS_WAVEVIEW (object);
-
        if (GTK_OBJECT_CLASS (parent_class)->destroy)
                (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 }
        if (GTK_OBJECT_CLASS (parent_class)->destroy)
                (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 }
@@ -418,12 +430,12 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
 #if DEBUG_CACHE
        // printf("waveview->region_start == %lu\n",waveview->region_start);
        // c_stacktrace ();
 #if DEBUG_CACHE
        // printf("waveview->region_start == %lu\n",waveview->region_start);
        // c_stacktrace ();
-       printf ("\n\n=> 0x%x cache @ 0x%x range: %lu - %lu request: %lu - %lu (%lu frames)\n", 
+       printf ("\n\n=> 0x%x cache @ 0x%x range: %lu - %lu request: %lu - %lu (%lu frames)\n",
                waveview, cache,
                cache->start, cache->end,
                start_sample, end_sample, end_sample - start_sample);
 #endif
                waveview, cache,
                cache->start, cache->end,
                start_sample, end_sample, end_sample - start_sample);
 #endif
-               
+
        if (cache->start <= start_sample && cache->end >= end_sample) {
 #if DEBUG_CACHE
                // printf ("0x%x: cache hit for %lu-%lu (cache holds: %lu-%lu\n",
        if (cache->start <= start_sample && cache->end >= end_sample) {
 #if DEBUG_CACHE
                // printf ("0x%x: cache hit for %lu-%lu (cache holds: %lu-%lu\n",
@@ -433,11 +445,11 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
        }
 
        /* make sure the cache is at least twice as wide as the screen width, and put the start sample
        }
 
        /* make sure the cache is at least twice as wide as the screen width, and put the start sample
-          in the middle, ensuring that we cover the end_sample. 
+          in the middle, ensuring that we cover the end_sample.
        */
 
        /* Note the assumption that we have a 1:1 units:pixel ratio for the canvas. Its everywhere ... */
        */
 
        /* Note the assumption that we have a 1:1 units:pixel ratio for the canvas. Its everywhere ... */
-       
+
        half_width = (gulong) floor ((waveview->screen_width * waveview->samples_per_unit)/2.0 + 0.5);
 
        if (start_sample < half_width) {
        half_width = (gulong) floor ((waveview->screen_width * waveview->samples_per_unit)/2.0 + 0.5);
 
        if (start_sample < half_width) {
@@ -462,7 +474,7 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
        }
 
 #if DEBUG_CACHE
        }
 
 #if DEBUG_CACHE
-       fprintf (stderr, "AVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n", 
+       fprintf (stderr, "AVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n",
                 rf3, waveview->sourcefile_length_function (waveview->data_src, waveview->samples_per_unit),
                 waveview->region_start, start_sample, new_cache_start);
 #endif
                 rf3, waveview->sourcefile_length_function (waveview->data_src, waveview->samples_per_unit),
                 waveview->region_start, start_sample, new_cache_start);
 #endif
@@ -489,7 +501,7 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
        ostart = new_cache_start;
 
 #ifdef CACHE_MEMMOVE_OPTIMIZATION
        ostart = new_cache_start;
 
 #ifdef CACHE_MEMMOVE_OPTIMIZATION
-       
+
        /* data is not entirely in the cache, so go fetch it, making sure to fill the cache */
 
        /* some of the required cache entries are in the cache, but in the wrong
        /* data is not entirely in the cache, so go fetch it, making sure to fill the cache */
 
        /* some of the required cache entries are in the cache, but in the wrong
@@ -497,24 +509,24 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
        */
 
        if (cache->start < new_cache_start && new_cache_start < cache->end) {
        */
 
        if (cache->start < new_cache_start && new_cache_start < cache->end) {
-               
-               /* case one: the common area is at the end of the existing cache. move it 
+
+               /* case one: the common area is at the end of the existing cache. move it
                   to the beginning of the cache, and set up to refill whatever remains.
                   to the beginning of the cache, and set up to refill whatever remains.
-                  
-                  
+
+
                           wv->cache_start                                        wv->cache_end
                           |-------------------------------------------------------| cache
                                                               |--------------------------------| requested
                                                               <------------------->
                                                                     "present"
                           wv->cache_start                                        wv->cache_end
                           |-------------------------------------------------------| cache
                                                               |--------------------------------| requested
                                                               <------------------->
                                                                     "present"
-                                                           new_cache_start                      new_cache_end       
+                                                           new_cache_start                      new_cache_end
                */
                */
-                               
+
 
                present_frames = cache->end - new_cache_start;
                present_entries = (gulong) floor (present_frames / waveview->samples_per_unit);
 
 
                present_frames = cache->end - new_cache_start;
                present_entries = (gulong) floor (present_frames / waveview->samples_per_unit);
 
-#if DEBUG_CACHE                
+#if DEBUG_CACHE
                fprintf (stderr, "existing material at end of current cache, move to start of new cache\n"
                         "\tcopy from %lu to start\n", cache->data_size - present_entries);
 #endif
                fprintf (stderr, "existing material at end of current cache, move to start of new cache\n"
                         "\tcopy from %lu to start\n", cache->data_size - present_entries);
 #endif
@@ -522,7 +534,7 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
                memmove (&cache->data[0],
                         &cache->data[cache->data_size - present_entries],
                         present_entries * sizeof (GnomeCanvasWaveViewCacheEntry));
                memmove (&cache->data[0],
                         &cache->data[cache->data_size - present_entries],
                         present_entries * sizeof (GnomeCanvasWaveViewCacheEntry));
-               
+
 #if DEBUG_CACHE
                fprintf (stderr, "satisfied %lu of %lu frames, offset = %lu, will start at %lu (ptr = 0x%x)\n",
                         present_frames, required_frames, present_entries, new_cache_start + present_entries,
 #if DEBUG_CACHE
                fprintf (stderr, "satisfied %lu of %lu frames, offset = %lu, will start at %lu (ptr = 0x%x)\n",
                         present_frames, required_frames, present_entries, new_cache_start + present_entries,
@@ -536,8 +548,8 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
 
        } else if (new_cache_end > cache->start && new_cache_end < cache->end) {
 
 
        } else if (new_cache_end > cache->start && new_cache_end < cache->end) {
 
-               /* case two: the common area lives at the beginning of the existing cache. 
-                  
+               /* case two: the common area lives at the beginning of the existing cache.
+
                                             wv->cache_start                                      wv->cache_end
                                             |-----------------------------------------------------|
                               |--------------------------------|
                                             wv->cache_start                                      wv->cache_end
                                             |-----------------------------------------------------|
                               |--------------------------------|
@@ -546,15 +558,15 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
 
                              new_cache_start                      new_cache_end
                */
 
                              new_cache_start                      new_cache_end
                */
-               
+
                present_frames = new_cache_end - cache->start;
                present_entries = (gulong) floor (present_frames / waveview->samples_per_unit);
 
                memmove (&cache->data[cache->data_size - present_entries],
                         &cache->data[0],
                         present_entries * sizeof (GnomeCanvasWaveViewCacheEntry));
                present_frames = new_cache_end - cache->start;
                present_entries = (gulong) floor (present_frames / waveview->samples_per_unit);
 
                memmove (&cache->data[cache->data_size - present_entries],
                         &cache->data[0],
                         present_entries * sizeof (GnomeCanvasWaveViewCacheEntry));
-               
-#if DEBUG_CACHE                
+
+#if DEBUG_CACHE
                fprintf (stderr, "existing material at start of current cache, move to start of end cache\n");
 #endif
 
                fprintf (stderr, "existing material at start of current cache, move to start of end cache\n");
 #endif
 
@@ -568,7 +580,7 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
                offset = 0;
                required_frames -= present_frames;
 
                offset = 0;
                required_frames -= present_frames;
 
-               
+
        } else {
                copied = 0;
                offset = 0;
        } else {
                copied = 0;
                offset = 0;
@@ -605,7 +617,7 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
                waveview->peak_function (waveview->data_src, npeaks, new_cache_start, required_frames, cache->data + offset, waveview->channel,waveview->samples_per_unit);
 
                /* take into account any copied peaks */
                waveview->peak_function (waveview->data_src, npeaks, new_cache_start, required_frames, cache->data + offset, waveview->channel,waveview->samples_per_unit);
 
                /* take into account any copied peaks */
-               
+
                npeaks += copied;
        } else {
                npeaks = copied;
                npeaks += copied;
        } else {
                npeaks = copied;
@@ -634,27 +646,27 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
                }
 
                free (gain);
                }
 
                free (gain);
-       
+
        }
 
        /* do optional log scaling.  this implementation is not particularly efficient */
        }
 
        /* do optional log scaling.  this implementation is not particularly efficient */
-       
+
        if (waveview->logscaled) {
                guint32 n;
                GnomeCanvasWaveViewCacheEntry* buf = cache->data;
        if (waveview->logscaled) {
                guint32 n;
                GnomeCanvasWaveViewCacheEntry* buf = cache->data;
-               
+
                for (n = 0; n < cache->data_size; ++n) {
 
                        if (buf[n].max > 0.0f) {
                for (n = 0; n < cache->data_size; ++n) {
 
                        if (buf[n].max > 0.0f) {
-                               buf[n].max = alt_log_meter(coefficient_to_dB(buf[n].max));
+                               buf[n].max = alt_log_meter(fast_coefficient_to_dB(buf[n].max));
                        } else if (buf[n].max < 0.0f) {
                        } else if (buf[n].max < 0.0f) {
-                               buf[n].max = -alt_log_meter(coefficient_to_dB(-buf[n].max));
+                               buf[n].max = -alt_log_meter(fast_coefficient_to_dB(-buf[n].max));
                        }
                        }
-                       
+
                        if (buf[n].min > 0.0f) {
                        if (buf[n].min > 0.0f) {
-                               buf[n].min = alt_log_meter(coefficient_to_dB(buf[n].min));
+                               buf[n].min = alt_log_meter(fast_coefficient_to_dB(buf[n].min));
                        } else if (buf[n].min < 0.0f) {
                        } else if (buf[n].min < 0.0f) {
-                               buf[n].min = -alt_log_meter(coefficient_to_dB(-buf[n].min));
+                               buf[n].min = -alt_log_meter(fast_coefficient_to_dB(-buf[n].min));
                        }
                }
        }
                        }
                }
        }
@@ -664,7 +676,7 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
 
   out:
 #if DEBUG_CACHE
 
   out:
 #if DEBUG_CACHE
-       fprintf (stderr, "return cache index = %d\n", 
+       fprintf (stderr, "return cache index = %d\n",
                 (guint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5));
 #endif
        return (guint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5);
                 (guint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5));
 #endif
        return (guint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5);
@@ -680,7 +692,7 @@ gnome_canvas_waveview_set_data_src (GnomeCanvasWaveView *waveview, void *data_sr
                        waveview->reload_cache_in_render = TRUE;
                        return;
                }
                        waveview->reload_cache_in_render = TRUE;
                        return;
                }
-       
+
                waveview->cache->start  = 0;
                waveview->cache->end = 0;
        }
                waveview->cache->start  = 0;
                waveview->cache->end = 0;
        }
@@ -694,11 +706,11 @@ gnome_canvas_waveview_set_channel (GnomeCanvasWaveView *waveview, guint32 chan)
        if (waveview->channel == chan) {
                return;
        }
        if (waveview->channel == chan) {
                return;
        }
-       
+
        waveview->channel = chan;
 }
 
        waveview->channel = chan;
 }
 
-static void 
+static void
 gnome_canvas_waveview_reset_bounds (GnomeCanvasItem *item)
 
 {
 gnome_canvas_waveview_reset_bounds (GnomeCanvasItem *item)
 
 {
@@ -727,8 +739,8 @@ gnome_canvas_waveview_reset_bounds (GnomeCanvasItem *item)
        gnome_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2);
 }
 
        gnome_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2);
 }
 
-/* 
- * CANVAS CALLBACKS 
+/*
+ * CANVAS CALLBACKS
  */
 
 static void
  */
 
 static void
@@ -738,6 +750,8 @@ gnome_canvas_waveview_set_property (GObject      *object,
                                    GParamSpec   *pspec)
 
 {
                                    GParamSpec   *pspec)
 
 {
+       (void) pspec;
+
        GnomeCanvasItem *item;
        GnomeCanvasWaveView *waveview;
        int redraw = FALSE;
        GnomeCanvasItem *item;
        GnomeCanvasWaveView *waveview;
        int redraw = FALSE;
@@ -749,6 +763,7 @@ gnome_canvas_waveview_set_property (GObject      *object,
        item = GNOME_CANVAS_ITEM (object);
        waveview = GNOME_CANVAS_WAVEVIEW (object);
 
        item = GNOME_CANVAS_ITEM (object);
        waveview = GNOME_CANVAS_WAVEVIEW (object);
 
+       void * ptr;
        switch (prop_id) {
        case PROP_DATA_SRC:
                gnome_canvas_waveview_set_data_src (waveview, g_value_get_pointer(value));
        switch (prop_id) {
        case PROP_DATA_SRC:
                gnome_canvas_waveview_set_data_src (waveview, g_value_get_pointer(value));
@@ -761,23 +776,27 @@ gnome_canvas_waveview_set_property (GObject      *object,
                break;
 
        case PROP_LENGTH_FUNCTION:
                break;
 
        case PROP_LENGTH_FUNCTION:
-               waveview->length_function = g_value_get_pointer(value);
+               ptr = g_value_get_pointer(value);
+               waveview->length_function = POSIX_FUNC_PTR_CAST(waveview_length_function_t, ptr);
                redraw = TRUE;
                break;
 
        case PROP_SOURCEFILE_LENGTH_FUNCTION:
                redraw = TRUE;
                break;
 
        case PROP_SOURCEFILE_LENGTH_FUNCTION:
-               waveview->sourcefile_length_function = g_value_get_pointer(value);
+               ptr = g_value_get_pointer(value);
+               waveview->sourcefile_length_function = POSIX_FUNC_PTR_CAST(waveview_sourcefile_length_function_t, ptr);
                redraw = TRUE;
                break;
 
        case PROP_PEAK_FUNCTION:
                redraw = TRUE;
                break;
 
        case PROP_PEAK_FUNCTION:
-               waveview->peak_function = g_value_get_pointer(value);
+               ptr = g_value_get_pointer(value);
+               waveview->peak_function = POSIX_FUNC_PTR_CAST(waveview_peak_function_t, ptr);
                redraw = TRUE;
                break;
 
        case PROP_GAIN_FUNCTION:
                redraw = TRUE;
                break;
 
        case PROP_GAIN_FUNCTION:
-               waveview->gain_curve_function = g_value_get_pointer(value);
-               redraw = TRUE;
+               ptr = g_value_get_pointer(value);
+               waveview->gain_curve_function = POSIX_FUNC_PTR_CAST(waveview_gain_curve_function_t, ptr);
+                        redraw = TRUE;
                break;
 
        case PROP_GAIN_SRC:
                break;
 
        case PROP_GAIN_SRC:
@@ -927,8 +946,8 @@ gnome_canvas_waveview_get_property (
                GValue       *value,
                GParamSpec   *pspec)
 {
                GValue       *value,
                GParamSpec   *pspec)
 {
-       
-   
+
+
        g_return_if_fail (object != NULL);
        g_return_if_fail (GNOME_IS_CANVAS_WAVEVIEW (object));
 
        g_return_if_fail (object != NULL);
        g_return_if_fail (GNOME_IS_CANVAS_WAVEVIEW (object));
 
@@ -944,19 +963,19 @@ gnome_canvas_waveview_get_property (
                break;
 
        case PROP_LENGTH_FUNCTION:
                break;
 
        case PROP_LENGTH_FUNCTION:
-               g_value_set_pointer(value, waveview->length_function);
+               g_value_set_pointer(value, POSIX_FUNC_PTR_CAST(void*, waveview->length_function));
                break;
 
        case PROP_SOURCEFILE_LENGTH_FUNCTION:
                break;
 
        case PROP_SOURCEFILE_LENGTH_FUNCTION:
-               g_value_set_pointer(value, waveview->sourcefile_length_function);
+               g_value_set_pointer(value, POSIX_FUNC_PTR_CAST(void*, waveview->sourcefile_length_function));
                break;
 
        case PROP_PEAK_FUNCTION:
                break;
 
        case PROP_PEAK_FUNCTION:
-               g_value_set_pointer(value, waveview->peak_function);
+               g_value_set_pointer(value, POSIX_FUNC_PTR_CAST(void*, waveview->peak_function));
                break;
 
        case PROP_GAIN_FUNCTION:
                break;
 
        case PROP_GAIN_FUNCTION:
-               g_value_set_pointer(value, waveview->gain_curve_function);
+               g_value_set_pointer(value, POSIX_FUNC_PTR_CAST(void*, waveview->gain_curve_function));
                break;
 
        case PROP_GAIN_SRC:
                break;
 
        case PROP_GAIN_SRC:
@@ -1081,11 +1100,11 @@ gnome_canvas_waveview_update (GnomeCanvasItem *item, double *affine, ArtSVP *cli
                      &waveview->fill_a);
 
 //     check_cache (waveview, "end of update");
                      &waveview->fill_a);
 
 //     check_cache (waveview, "end of update");
-}                                 
+}
 
 static void
 
 static void
-gnome_canvas_waveview_render (GnomeCanvasItem *item,
-                           GnomeCanvasBuf *buf)
+gnome_canvas_waveview_gradient_render (GnomeCanvasItem *item,
+                                      GnomeCanvasBuf *buf)
 {
        GnomeCanvasWaveView *waveview;
        gulong s1, s2;
 {
        GnomeCanvasWaveView *waveview;
        gulong s1, s2;
@@ -1184,7 +1203,7 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
 
        clip_length = MIN(5,(waveview->height/4));
 
 
        clip_length = MIN(5,(waveview->height/4));
 
-       /* 
+       /*
           Now draw each line, clipping it appropriately. The clipping
           is done by the macros PAINT_FOO().
        */
           Now draw each line, clipping it appropriately. The clipping
           is done by the macros PAINT_FOO().
        */
@@ -1204,6 +1223,9 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                int next_clip_max = 0;
                int next_clip_min = 0;
 
                int next_clip_max = 0;
                int next_clip_min = 0;
 
+               int wave_middle = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
+               int wave_top = (int) rint ((item->y1) * item->canvas->pixels_per_unit);
+
                if (s1 < waveview->samples_per_unit) {
                        /* we haven't got a prev vars to compare with, so outline the whole line here */
                        prev_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
                if (s1 < waveview->samples_per_unit) {
                        /* we haven't got a prev vars to compare with, so outline the whole line here */
                        prev_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
@@ -1238,40 +1260,40 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                        guint index = cache_index + (end - begin);
 
                        if (index >= waveview->cache->data_size) {
                        guint index = cache_index + (end - begin);
 
                        if (index >= waveview->cache->data_size) {
-                               
+
                                /* the data we want is off the end of the cache, which must mean its beyond
                                   the end of the region's source; hence the peak values are 0 */
                                last_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
                                last_pymin = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
                                /* the data we want is off the end of the cache, which must mean its beyond
                                   the end of the region's source; hence the peak values are 0 */
                                last_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
                                last_pymin = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
-                               
+
                        } else {
                        } else {
-                               
+
                                last_pymax = (int) rint ((item->y1 + origin - MIN(waveview->cache->data[index].max, 1.0) * half_height) * item->canvas->pixels_per_unit);
                                last_pymin = (int) rint ((item->y1 + origin - MAX(waveview->cache->data[index].min, -1.0) * half_height) * item->canvas->pixels_per_unit);
                                last_pymax = (int) rint ((item->y1 + origin - MIN(waveview->cache->data[index].max, 1.0) * half_height) * item->canvas->pixels_per_unit);
                                last_pymin = (int) rint ((item->y1 + origin - MAX(waveview->cache->data[index].min, -1.0) * half_height) * item->canvas->pixels_per_unit);
-                               
+
                        }
                        }
-                               
+
                }
 
                }
 
-               /* 
+               /*
                 * initialize NEXT* variables for the first run, duplicated in the loop for speed
                 */
                max = waveview->cache->data[cache_index].max;
                min = waveview->cache->data[cache_index].min;
                 * initialize NEXT* variables for the first run, duplicated in the loop for speed
                 */
                max = waveview->cache->data[cache_index].max;
                min = waveview->cache->data[cache_index].min;
-               
+
                if (max >= 1.0) {
                        max = 1.0;
                        next_clip_max = 1;
                }
                if (max >= 1.0) {
                        max = 1.0;
                        next_clip_max = 1;
                }
-               
+
                if (min <= -1.0) {
                        min = -1.0;
                        next_clip_min = 1;
                }
                if (min <= -1.0) {
                        min = -1.0;
                        next_clip_min = 1;
                }
-               
+
                max *= half_height;
                min *= half_height;
                max *= half_height;
                min *= half_height;
-               
+
                next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
                next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
 
                next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
                next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
 
@@ -1309,7 +1331,7 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                                        max = 1.0;
                                        next_clip_max = 1;
                                }
                                        max = 1.0;
                                        next_clip_max = 1;
                                }
-                               
+
                                if (min <= -1.0) {
                                        min = -1.0;
                                        next_clip_min = 1;
                                if (min <= -1.0) {
                                        min = -1.0;
                                        next_clip_min = 1;
@@ -1317,11 +1339,11 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
 
                                max *= half_height;
                                min *= half_height;
 
                                max *= half_height;
                                min *= half_height;
-                               
+
                                next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
                                next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
                        }
                                next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
                                next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
                        }
-                       
+
                        /* render */
                        if (pymax == pymin) {
                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
                        /* render */
                        if (pymax == pymin) {
                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
@@ -1336,10 +1358,10 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                                        if(pymax == fill_max) {
                                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
                                                ++fill_max;
                                        if(pymax == fill_max) {
                                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
                                                ++fill_max;
+                                       } else {
+                                               PAINT_VERTA_GR(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max, wave_middle, wave_top);
                                        }
                                        }
-                                       else {
-                                               PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max);
-                                       }
+
                                }
 
                                if((prev_pymin > pymin && next_pymin > pymin) ||
                                }
 
                                if((prev_pymin > pymin && next_pymin > pymin) ||
@@ -1353,12 +1375,12 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
                                        }
                                        else {
                                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
                                        }
                                        else {
-                                               PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, fill_min, pymin);
+                                               PAINT_VERTA_GR(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, fill_min, pymin, wave_middle, wave_top);
                                        }
                                }
 
                                if(fill_max < fill_min) {
                                        }
                                }
 
                                if(fill_max < fill_min) {
-                                       PAINT_VERTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max, fill_min);
+                                       PAINT_VERTA_GR(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max, fill_min, wave_middle, wave_top);
                                }
                                else if(fill_max == fill_min) {
                                        PAINT_DOTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max);
                                }
                                else if(fill_max == fill_min) {
                                        PAINT_DOTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max);
@@ -1366,11 +1388,16 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                        }
 
                        if (clip_max) {
                        }
 
                        if (clip_max) {
-                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax + clip_length);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x + 1, pymax, pymax + (clip_length -1));
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x - 1, pymax, pymax + (clip_length - 1));
+
                        }
                        }
-                       
+
                        if (clip_min) {
                        if (clip_min) {
-                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a , x, pymin - clip_length, pymin);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x + 1, pymin - (clip_length - 1), pymin);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x - 1, pymin - (clip_length - 1), pymin);
                        }
 
                        prev_pymax = pymax;
                        }
 
                        prev_pymax = pymax;
@@ -1386,6 +1413,9 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                int next_clip_max = 0;
                int next_clip_min = 0;
 
                int next_clip_max = 0;
                int next_clip_min = 0;
 
+               int wave_middle = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
+               int wave_top = (int) rint ((item->y1) * item->canvas->pixels_per_unit);
+
                // for rectified, this stays constant throughout the loop
                pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
 
                // for rectified, this stays constant throughout the loop
                pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
 
@@ -1424,7 +1454,7 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                if(last_pymax < 0) {
                        /* take the index of one sample right of what we render */
                        int index = cache_index + (end - begin);
                if(last_pymax < 0) {
                        /* take the index of one sample right of what we render */
                        int index = cache_index + (end - begin);
-                       
+
                        max = MIN(waveview->cache->data[index].max, 1.0);
                        min = MAX(waveview->cache->data[index].min, -1.0);
 
                        max = MIN(waveview->cache->data[index].max, 1.0);
                        min = MAX(waveview->cache->data[index].min, -1.0);
 
@@ -1435,26 +1465,26 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                        last_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
                }
 
                        last_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
                }
 
-               /* 
+               /*
                 * initialize NEXT* variables for the first run, duplicated in the loop for speed
                 */
                max = waveview->cache->data[cache_index].max;
                min = waveview->cache->data[cache_index].min;
                 * initialize NEXT* variables for the first run, duplicated in the loop for speed
                 */
                max = waveview->cache->data[cache_index].max;
                min = waveview->cache->data[cache_index].min;
-               
+
                if (max >= 1.0) {
                        max = 1.0;
                        next_clip_max = 1;
                }
                if (max >= 1.0) {
                        max = 1.0;
                        next_clip_max = 1;
                }
-               
+
                if (min <= -1.0) {
                        min = -1.0;
                        next_clip_min = 1;
                }
                if (min <= -1.0) {
                        min = -1.0;
                        next_clip_min = 1;
                }
-               
+
                if (fabs (min) > fabs (max)) {
                        max = fabs (min);
                if (fabs (min) > fabs (max)) {
                        max = fabs (min);
-               } 
-               
+               }
+
                next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
 
                /*
                next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
 
                /*
@@ -1477,24 +1507,24 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
 
                                max = waveview->cache->data[cache_index].max;
                                min = waveview->cache->data[cache_index].min;
 
                                max = waveview->cache->data[cache_index].max;
                                min = waveview->cache->data[cache_index].min;
-                               
+
                                if (max >= 1.0) {
                                        max = 1.0;
                                        next_clip_max = 1;
                                }
                                if (max >= 1.0) {
                                        max = 1.0;
                                        next_clip_max = 1;
                                }
-                               
+
                                if (min <= -1.0) {
                                        min = -1.0;
                                        next_clip_min = 1;
                                }
                                if (min <= -1.0) {
                                        min = -1.0;
                                        next_clip_min = 1;
                                }
-                               
+
                                if (fabs (min) > fabs (max)) {
                                        max = fabs (min);
                                if (fabs (min) > fabs (max)) {
                                        max = fabs (min);
-                               } 
-                               
+                               }
+
                                next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
                        }
                                next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
                        }
-                       
+
                        /* render */
                        if (pymax == pymin) {
                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
                        /* render */
                        if (pymax == pymin) {
                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
@@ -1511,7 +1541,7 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                                                ++fill_max;
                                        }
                                        else {
                                                ++fill_max;
                                        }
                                        else {
-                                               PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max);
+                                               PAINT_VERTA_GR(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max, wave_middle, wave_top);
                                        }
                                }
 
                                        }
                                }
 
@@ -1524,11 +1554,15 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                        }
 
                        if (clip_max) {
                        }
 
                        if (clip_max) {
-                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax + clip_length);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x + 1, pymax, pymax + (clip_length -1));
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x - 1, pymax, pymax + (clip_length - 1));
                        }
                        }
-                       
+
                        if (clip_min) {
                        if (clip_min) {
-                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a , x, pymin - clip_length, pymin);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x + 1, pymin - (clip_length - 1), pymin);
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x - 1, pymin - (clip_length - 1), pymin);
                        }
 
                        prev_pymax = pymax;
                        }
 
                        prev_pymax = pymax;
@@ -1538,78 +1572,77 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
                cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
 
                for (x = begin; x < end; x++) {
                cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
 
                for (x = begin; x < end; x++) {
-                       
+
                        double max, min;
                        int clip_max, clip_min;
                        double max, min;
                        int clip_max, clip_min;
-                       
+
                        clip_max = 0;
                        clip_min = 0;
                        clip_max = 0;
                        clip_min = 0;
-                       
+
                        max = waveview->cache->data[cache_index].max;
                        min = waveview->cache->data[cache_index].min;
                        max = waveview->cache->data[cache_index].max;
                        min = waveview->cache->data[cache_index].min;
-                       
+
                        if (max >= 1.0) {
                                max = 1.0;
                                clip_max = 1;
                        }
                        if (max >= 1.0) {
                                max = 1.0;
                                clip_max = 1;
                        }
-                       
+
                        if (min <= -1.0) {
                                min = -1.0;
                                clip_min = 1;
                        }
                        if (min <= -1.0) {
                                min = -1.0;
                                clip_min = 1;
                        }
-                       
+
                        if (rectify) {
                        if (rectify) {
-                               
+
                                if (fabs (min) > fabs (max)) {
                                        max = fabs (min);
                                if (fabs (min) > fabs (max)) {
                                        max = fabs (min);
-                               } 
-                               
+                               }
+
                                max = max * waveview->height;
                                max = max * waveview->height;
-                               
+
                                pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit);
                                pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
                                pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit);
                                pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
-                               
+
                        } else {
                        } else {
-                               
+
                                max = max * half_height;
                                min = min * half_height;
                                max = max * half_height;
                                min = min * half_height;
-                               
+
                                pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
                                pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
                        }
                                pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
                                pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
                        }
-                       
+
                        /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax,
                           or, if samples_per_unit == 1, then a dot at each location.
                        */
                        /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax,
                           or, if samples_per_unit == 1, then a dot at each location.
                        */
-                       
+
                        if (pymax == pymin) {
                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
                        } else {
                                PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin);
                        }
                        if (pymax == pymin) {
                                PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
                        } else {
                                PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin);
                        }
-                       
+
                        /* show clipped waveforms with small red lines */
                        /* show clipped waveforms with small red lines */
-                       
+
                        if (clip_max) {
                                PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
                        }
                        if (clip_max) {
                                PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
                        }
-                       
+
                        if (clip_min) {
                                PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
                        }
 
                        /* presto, we're done */
                        if (clip_min) {
                                PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
                        }
 
                        /* presto, we're done */
-               
+
                        cache_index++;
                }
        }
 
                        cache_index++;
                }
        }
 
-       if (!waveview->rectified && waveview->zero_line) {
+       if (!waveview->rectified && waveview->zero_line && waveview->height >= 100) {
                // Paint zeroline.
                // Paint zeroline.
-               //PAINT_HORIZA(buf, waveview->zero_r, waveview->zero_g, waveview->zero_b, waveview->zero_a, begin, endi-1, origin );
-               
+
                unsigned char zero_r, zero_g, zero_b, zero_a;
                unsigned char zero_r, zero_g, zero_b, zero_a;
-               UINT_TO_RGBA( waveview->zero_color, &zero_r, &zero_g, &zero_b, &zero_a );
+               UINT_TO_RGBA( waveview->zero_color, &zero_r, &zero_g, &zero_b, &zero_a);
                int zeroline_y = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
                PAINT_HORIZA(buf, zero_r, zero_g, zero_b, zero_a, zbegin, zend, zeroline_y);
        }
                int zeroline_y = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
                PAINT_HORIZA(buf, zero_r, zero_g, zero_b, zero_a, zbegin, zend, zeroline_y);
        }
@@ -1618,105 +1651,645 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
 }
 
 static void
 }
 
 static void
-gnome_canvas_waveview_draw (GnomeCanvasItem *item,
-                           GdkDrawable *drawable,
-                           int x, int y,
-                           int width, int height)
+gnome_canvas_waveview_flat_render (GnomeCanvasItem *item,
+                                  GnomeCanvasBuf *buf)
 {
        GnomeCanvasWaveView *waveview;
 {
        GnomeCanvasWaveView *waveview;
-       cairo_t* cr;
        gulong s1, s2;
        gulong s1, s2;
-       int cache_index;
-       gboolean rectify;
-       double origin;
-       double clip_length;
-       double xoff;
-       double yoff = 0.0;
-       double ulx;
-       double uly;
-       double lrx;
-       double lry;
+       int clip_length = 0;
+       int pymin, pymax;
+       guint cache_index;
+       double half_height;
+       int x;
+       char rectify;
 
        waveview = GNOME_CANVAS_WAVEVIEW (item);
 
 
        waveview = GNOME_CANVAS_WAVEVIEW (item);
 
-       /* compute intersection of Drawable area and waveview,
-          in canvas coordinate space
-       */
+//     check_cache (waveview, "start of render");
 
 
-       if (x > waveview->bbox_ulx) {
-               ulx = x;
-       } else {
-               ulx = waveview->bbox_ulx;
+       if (parent_class->render) {
+               (*parent_class->render) (item, buf);
        }
 
        }
 
-       if (y > waveview->bbox_uly) {
-               uly = y;
-       } else {
-               uly = waveview->bbox_uly;
+       if (buf->is_bg) {
+               gnome_canvas_buf_ensure_buf (buf);
+               buf->is_bg = FALSE;
        }
 
        }
 
-       if (x + width > waveview->bbox_lrx) {
-               lrx = waveview->bbox_lrx;
-       } else {
-               lrx = x + width;
-       }
+       /* a "unit" means a pixel */
 
 
-       if (y + height > waveview->bbox_lry) {
-               lry = waveview->bbox_lry;
-       } else {
-               lry = y + height;
+       /* begin: render start x (units) */
+       int const begin = MAX (waveview->bbox_ulx, buf->rect.x0);
+
+        /* zbegin: start x for zero line (units) */
+       int const zbegin = (begin == waveview->bbox_ulx) ? (begin + 1) : begin;
+
+       /* end: render end x (units) */
+       int const end = (waveview->bbox_lrx >= 0) ? MIN (waveview->bbox_lrx,buf->rect.x1) : buf->rect.x1;
+
+       /* zend: end x for zero-line (units) */
+       int const zend = (end == waveview->bbox_lrx) ? (end - 1) : end;
+
+       if (begin == end) {
+               return;
        }
 
        }
 
-       /* figure out which samples we need for the resulting intersection */
+       /* s1: start sample
+          s2: end sample
+       */
 
 
-       s1 = floor ((ulx - waveview->bbox_ulx) * waveview->samples_per_unit) ;
+       s1 = floor ((begin - waveview->bbox_ulx) * waveview->samples_per_unit);
 
 
-       if (lrx == waveview->bbox_lrx) {
+       // fprintf (stderr, "0x%x begins at sample %f\n", waveview, waveview->bbox_ulx * waveview->samples_per_unit);
+
+       if (end == waveview->bbox_lrx) {
                /* This avoids minor rounding errors when we have the
                   entire region visible.
                */
                s2 = waveview->samples;
        } else {
                /* This avoids minor rounding errors when we have the
                   entire region visible.
                */
                s2 = waveview->samples;
        } else {
-               s2 = s1 + floor ((lrx - ulx) * waveview->samples_per_unit);
+               s2 = s1 + floor ((end - begin) * waveview->samples_per_unit);
        }
 
        }
 
-       /* translate back to buffer coordinate space */
+#if 0
+       printf ("0x%x r (%d..%d)(%d..%d) bbox (%d..%d)(%d..%d)"
+               " b/e %d..%d s= %lu..%lu @ %f\n",
+               waveview,
+               buf->rect.x0,
+               buf->rect.x1,
+               buf->rect.y0,
+               buf->rect.y1,
+               waveview->bbox_ulx,
+               waveview->bbox_lrx,
+               waveview->bbox_uly,
+               waveview->bbox_lry,
+               begin, end, s1, s2,
+               waveview->samples_per_unit);
+#endif
 
 
-       ulx -= x;
-       uly -= y;
-       lrx -= x;
-       lry -= y;
+       /* now ensure that the cache is full and properly
+          positioned.
+       */
+
+//     check_cache (waveview, "pre-ensure");
+
+       if (waveview->cache_updater && waveview->reload_cache_in_render) {
+               waveview->cache->start = 0;
+               waveview->cache->end = 0;
+               waveview->reload_cache_in_render = FALSE;
+       }
+
+//     check_cache (waveview, "post-ensure");
 
        /* don't rectify at single-sample zoom */
 
        /* don't rectify at single-sample zoom */
-       if(waveview->rectified && waveview->samples_per_unit > 1.0) {
+       if (waveview->rectified && waveview->samples_per_unit > 1) {
                rectify = TRUE;
                rectify = TRUE;
-       } else {
+       }
+       else {
                rectify = FALSE;
        }
 
        clip_length = MIN(5,(waveview->height/4));
 
                rectify = FALSE;
        }
 
        clip_length = MIN(5,(waveview->height/4));
 
-       cr = gdk_cairo_create (drawable);
-       cairo_set_line_width (cr, 0.5);
-
-       origin = waveview->bbox_uly - y + waveview->half_height;
-
-       cairo_rectangle (cr, ulx, uly, lrx - ulx, lry - uly);
-       cairo_clip (cr);
+       /*
+          Now draw each line, clipping it appropriately. The clipping
+          is done by the macros PAINT_FOO().
+       */
 
 
-       if (waveview->cache_updater && waveview->reload_cache_in_render) {
-               waveview->cache->start = 0;
-               waveview->cache->end = 0;
-               waveview->reload_cache_in_render = FALSE;
-       }
+       half_height = waveview->half_height;
 
 
-       cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
+/* this makes it slightly easier to comprehend whats going on */
+#define origin half_height
 
 
-#if 0
-       printf ("%p r (%d,%d)(%d,%d)[%d x %d] bbox (%d,%d)(%d,%d)[%d x %d]"
-               " draw (%.1f,%.1f)(%.1f,%.1f)[%.1f x %.1f] s= %lu..%lu\n",
-               waveview,
-               x, y, 
+       if (waveview->filled && !rectify) {
+               int prev_pymin = 1;
+               int prev_pymax = 0;
+               int last_pymin = 1;
+               int last_pymax = 0;
+               int next_pymin, next_pymax;
+               double max, min;
+               int next_clip_max = 0;
+               int next_clip_min = 0;
+
+               if (s1 < waveview->samples_per_unit) {
+                       /* we haven't got a prev vars to compare with, so outline the whole line here */
+                       prev_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
+                       prev_pymin = prev_pymax;
+               }
+               else {
+                       s1 -= waveview->samples_per_unit;
+               }
+
+               if(end == waveview->bbox_lrx) {
+                       /* we don't have the NEXT vars for the last sample */
+                       last_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
+                       last_pymin = last_pymax;
+               }
+               else {
+                       s2 += waveview->samples_per_unit;
+               }
+
+               cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
+
+               /*
+                * Compute the variables outside the rendering rect
+                */
+               if(prev_pymax != prev_pymin) {
+
+                       prev_pymax = (int) rint ((item->y1 + origin - MIN(waveview->cache->data[cache_index].max, 1.0) * half_height) * item->canvas->pixels_per_unit);
+                       prev_pymin = (int) rint ((item->y1 + origin - MAX(waveview->cache->data[cache_index].min, -1.0) * half_height) * item->canvas->pixels_per_unit);
+                       ++cache_index;
+               }
+               if(last_pymax != last_pymin) {
+                       /* take the index of one sample right of what we render */
+                       guint index = cache_index + (end - begin);
+
+                       if (index >= waveview->cache->data_size) {
+
+                               /* the data we want is off the end of the cache, which must mean its beyond
+                                  the end of the region's source; hence the peak values are 0 */
+                               last_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
+                               last_pymin = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
+
+                       } else {
+
+                               last_pymax = (int) rint ((item->y1 + origin - MIN(waveview->cache->data[index].max, 1.0) * half_height) * item->canvas->pixels_per_unit);
+                               last_pymin = (int) rint ((item->y1 + origin - MAX(waveview->cache->data[index].min, -1.0) * half_height) * item->canvas->pixels_per_unit);
+
+                       }
+
+               }
+
+               /*
+                * initialize NEXT* variables for the first run, duplicated in the loop for speed
+                */
+               max = waveview->cache->data[cache_index].max;
+               min = waveview->cache->data[cache_index].min;
+
+               if (max >= 1.0) {
+                       max = 1.0;
+                       next_clip_max = 1;
+               }
+
+               if (min <= -1.0) {
+                       min = -1.0;
+                       next_clip_min = 1;
+               }
+
+               max *= half_height;
+               min *= half_height;
+
+               next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
+               next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
+
+               /*
+                * And now the loop
+                */
+               for(x = begin; x < end; ++x) {
+                       int clip_max = next_clip_max;
+                       int clip_min = next_clip_min;
+                       int fill_max, fill_min;
+
+                       pymax = next_pymax;
+                       pymin = next_pymin;
+
+                       /* compute next */
+                       if(x == end - 1) {
+                               /*next is now the last column, which is outside the rendering rect, and possibly outside the region*/
+                               next_pymax = last_pymax;
+                               next_pymin = last_pymin;
+                       }
+                       else {
+                               ++cache_index;
+
+                               if (cache_index < waveview->cache->data_size) {
+                                       max = waveview->cache->data[cache_index].max;
+                                       min = waveview->cache->data[cache_index].min;
+                               } else {
+                                       max = min = 0;
+                               }
+
+                               next_clip_max = 0;
+                               next_clip_min = 0;
+
+                               if (max >= 1.0) {
+                                       max = 1.0;
+                                       next_clip_max = 1;
+                               }
+
+                               if (min <= -1.0) {
+                                       min = -1.0;
+                                       next_clip_min = 1;
+                               }
+
+                               max *= half_height;
+                               min *= half_height;
+
+                               next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
+                               next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
+                       }
+
+                       /* render */
+                       if (pymax == pymin) {
+                               PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+                       } else {
+                               if((prev_pymax < pymax && next_pymax < pymax) ||
+                                  (prev_pymax == pymax && next_pymax == pymax)) {
+                                       fill_max = pymax + 1;
+                                       PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
+                               }
+                               else {
+                                       fill_max = MAX(prev_pymax, next_pymax);
+                                       if(pymax == fill_max) {
+                                               PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
+                                               ++fill_max;
+                                       }
+                                       else {
+                                               PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max);
+                                       }
+                               }
+
+                               if((prev_pymin > pymin && next_pymin > pymin) ||
+                                  (prev_pymin == pymin && next_pymin == pymin)) {
+                                       fill_min = pymin - 1;
+                                       PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin-1);
+                               }
+                               else {
+                                       fill_min = MIN(prev_pymin, next_pymin);
+                                       if(pymin == fill_min) {
+                                               PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+                                       }
+                                       else {
+                                               PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, fill_min, pymin);
+                                       }
+                               }
+
+                               if(fill_max < fill_min) {
+                                       PAINT_VERTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max, fill_min);
+                               }
+                               else if(fill_max == fill_min) {
+                                       PAINT_DOTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max);
+                               }
+                       }
+
+                       if (clip_max) {
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+                       }
+
+                       if (clip_min) {
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+                       }
+
+                       prev_pymax = pymax;
+                       prev_pymin = pymin;
+               }
+
+       } else if (waveview->filled && rectify) {
+
+               int prev_pymax = -1;
+               int last_pymax = -1;
+               int next_pymax;
+               double max, min;
+               int next_clip_max = 0;
+               int next_clip_min = 0;
+
+               // for rectified, this stays constant throughout the loop
+               pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
+
+               if(s1 < waveview->samples_per_unit) {
+                       /* we haven't got a prev vars to compare with, so outline the whole line here */
+                       prev_pymax = pymin;
+               }
+               else {
+                       s1 -= waveview->samples_per_unit;
+               }
+
+               if(end == waveview->bbox_lrx) {
+                       /* we don't have the NEXT vars for the last sample */
+                       last_pymax = pymin;
+               }
+               else {
+                       s2 += waveview->samples_per_unit;
+               }
+
+               cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
+
+               /*
+                * Compute the variables outside the rendering rect
+                */
+               if(prev_pymax < 0) {
+                       max = MIN(waveview->cache->data[cache_index].max, 1.0);
+                       min = MAX(waveview->cache->data[cache_index].min, -1.0);
+
+                       if (fabs (min) > fabs (max)) {
+                               max = fabs (min);
+                       }
+
+                       prev_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
+                       ++cache_index;
+               }
+               if(last_pymax < 0) {
+                       /* take the index of one sample right of what we render */
+                       int index = cache_index + (end - begin);
+
+                       max = MIN(waveview->cache->data[index].max, 1.0);
+                       min = MAX(waveview->cache->data[index].min, -1.0);
+
+                       if (fabs (min) > fabs (max)) {
+                               max = fabs (min);
+                       }
+
+                       last_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
+               }
+
+               /*
+                * initialize NEXT* variables for the first run, duplicated in the loop for speed
+                */
+               max = waveview->cache->data[cache_index].max;
+               min = waveview->cache->data[cache_index].min;
+
+               if (max >= 1.0) {
+                       max = 1.0;
+                       next_clip_max = 1;
+               }
+
+               if (min <= -1.0) {
+                       min = -1.0;
+                       next_clip_min = 1;
+               }
+
+               if (fabs (min) > fabs (max)) {
+                       max = fabs (min);
+               }
+
+               next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
+
+               /*
+                * And now the loop
+                */
+               for(x = begin; x < end; ++x) {
+                       int clip_max = next_clip_max;
+                       int clip_min = next_clip_min;
+                       int fill_max;
+
+                       pymax = next_pymax;
+
+                       /* compute next */
+                       if(x == end - 1) {
+                               /*next is now the last column, which is outside the rendering rect, and possibly outside the region*/
+                               next_pymax = last_pymax;
+                       }
+                       else {
+                               ++cache_index;
+
+                               max = waveview->cache->data[cache_index].max;
+                               min = waveview->cache->data[cache_index].min;
+
+                               if (max >= 1.0) {
+                                       max = 1.0;
+                                       next_clip_max = 1;
+                               }
+
+                               if (min <= -1.0) {
+                                       min = -1.0;
+                                       next_clip_min = 1;
+                               }
+
+                               if (fabs (min) > fabs (max)) {
+                                       max = fabs (min);
+                               }
+
+                               next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
+                       }
+
+                       /* render */
+                       if (pymax == pymin) {
+                               PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+                       } else {
+                               if((prev_pymax < pymax && next_pymax < pymax) ||
+                                  (prev_pymax == pymax && next_pymax == pymax)) {
+                                       fill_max = pymax + 1;
+                                       PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
+                               }
+                               else {
+                                       fill_max = MAX(prev_pymax, next_pymax);
+                                       if(pymax == fill_max) {
+                                               PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
+                                               ++fill_max;
+                                       }
+                                       else {
+                                               PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max);
+                                       }
+                               }
+
+                               if(fill_max < pymin) {
+                                       PAINT_VERTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max, pymin);
+                               }
+                               else if(fill_max == pymin) {
+                                       PAINT_DOTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, pymin);
+                               }
+                       }
+
+                       if (clip_max) {
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+                       }
+
+                       if (clip_min) {
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+                       }
+
+                       prev_pymax = pymax;
+               }
+       }
+       else {
+               cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
+
+               for (x = begin; x < end; x++) {
+
+                       double max, min;
+                       int clip_max, clip_min;
+
+                       clip_max = 0;
+                       clip_min = 0;
+
+                       max = waveview->cache->data[cache_index].max;
+                       min = waveview->cache->data[cache_index].min;
+
+                       if (max >= 1.0) {
+                               max = 1.0;
+                               clip_max = 1;
+                       }
+
+                       if (min <= -1.0) {
+                               min = -1.0;
+                               clip_min = 1;
+                       }
+
+                       if (rectify) {
+
+                               if (fabs (min) > fabs (max)) {
+                                       max = fabs (min);
+                               }
+
+                               max = max * waveview->height;
+
+                               pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit);
+                               pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
+
+                       } else {
+
+                               max = max * half_height;
+                               min = min * half_height;
+
+                               pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
+                               pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
+                       }
+
+                       /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax,
+                          or, if samples_per_unit == 1, then a dot at each location.
+                       */
+
+                       if (pymax == pymin) {
+                               PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+                       } else {
+                               PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin);
+                       }
+
+                       /* show clipped waveforms with small red lines */
+
+                       if (clip_max) {
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+                       }
+
+                       if (clip_min) {
+                               PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+                       }
+
+                       /* presto, we're done */
+
+                       cache_index++;
+               }
+       }
+
+       if (!waveview->rectified && waveview->zero_line && waveview->height >= 100) {
+               // Paint zeroline.
+
+               unsigned char zero_r, zero_g, zero_b, zero_a;
+               UINT_TO_RGBA( waveview->zero_color, &zero_r, &zero_g, &zero_b, &zero_a);
+               int zeroline_y = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
+               PAINT_HORIZA(buf, zero_r, zero_g, zero_b, zero_a, zbegin, zend, zeroline_y);
+       }
+#undef origin
+}
+
+static void
+gnome_canvas_waveview_render (GnomeCanvasItem *item,
+                             GnomeCanvasBuf *buf)
+{
+       if (_gradient_rendering) {
+               gnome_canvas_waveview_gradient_render (item, buf);
+       } else {
+               gnome_canvas_waveview_flat_render (item, buf);
+       }
+}
+
+static void
+gnome_canvas_waveview_draw (GnomeCanvasItem *item,
+                           GdkDrawable *drawable,
+                           int x, int y,
+                           int width, int height)
+{
+       GnomeCanvasWaveView *waveview;
+       cairo_t* cr;
+       gulong s1, s2;
+       int cache_index;
+       gboolean rectify;
+       double origin;
+       double xoff;
+       double yoff = 0.0;
+       double ulx;
+       double uly;
+       double lrx;
+       double lry;
+
+       waveview = GNOME_CANVAS_WAVEVIEW (item);
+
+       /* compute intersection of Drawable area and waveview,
+          in canvas coordinate space
+       */
+
+       if (x > waveview->bbox_ulx) {
+               ulx = x;
+       } else {
+               ulx = waveview->bbox_ulx;
+       }
+
+       if (y > waveview->bbox_uly) {
+               uly = y;
+       } else {
+               uly = waveview->bbox_uly;
+       }
+
+       if (x + width > waveview->bbox_lrx) {
+               lrx = waveview->bbox_lrx;
+       } else {
+               lrx = x + width;
+       }
+
+       if (y + height > waveview->bbox_lry) {
+               lry = waveview->bbox_lry;
+       } else {
+               lry = y + height;
+       }
+
+       /* figure out which samples we need for the resulting intersection */
+
+       s1 = floor ((ulx - waveview->bbox_ulx) * waveview->samples_per_unit) ;
+
+       if (lrx == waveview->bbox_lrx) {
+               /* This avoids minor rounding errors when we have the
+                  entire region visible.
+               */
+               s2 = waveview->samples;
+       } else {
+               s2 = s1 + floor ((lrx - ulx) * waveview->samples_per_unit);
+       }
+
+       /* translate back to buffer coordinate space */
+
+       ulx -= x;
+       uly -= y;
+       lrx -= x;
+       lry -= y;
+
+       /* don't rectify at single-sample zoom */
+       if(waveview->rectified && waveview->samples_per_unit > 1.0) {
+               rectify = TRUE;
+       } else {
+               rectify = FALSE;
+       }
+
+       cr = gdk_cairo_create (drawable);
+       cairo_set_line_width (cr, 0.5);
+
+       origin = waveview->bbox_uly - y + waveview->half_height;
+
+       cairo_rectangle (cr, ulx, uly, lrx - ulx, lry - uly);
+       cairo_clip (cr);
+
+       if (waveview->cache_updater && waveview->reload_cache_in_render) {
+               waveview->cache->start = 0;
+               waveview->cache->end = 0;
+               waveview->reload_cache_in_render = FALSE;
+       }
+
+       cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
+
+#if 0
+       printf ("%p r (%d,%d)(%d,%d)[%d x %d] bbox (%d,%d)(%d,%d)[%d x %d]"
+               " draw (%.1f,%.1f)(%.1f,%.1f)[%.1f x %.1f] s= %lu..%lu\n",
+               waveview,
+               x, y,
                x + width,
                y + height,
                width,
                x + width,
                y + height,
                width,
@@ -1735,7 +2308,7 @@ gnome_canvas_waveview_draw (GnomeCanvasItem *item,
 #endif
 
        /* draw the top half */
 #endif
 
        /* draw the top half */
-       
+
        for (xoff = ulx; xoff < lrx; xoff++) {
                double max, min;
 
        for (xoff = ulx; xoff < lrx; xoff++) {
                double max, min;
 
@@ -1745,19 +2318,19 @@ gnome_canvas_waveview_draw (GnomeCanvasItem *item,
                if (min <= -1.0) {
                        min = -1.0;
                }
                if (min <= -1.0) {
                        min = -1.0;
                }
-               
+
                if (max >= 1.0) {
                        max = 1.0;
                }
                if (max >= 1.0) {
                        max = 1.0;
                }
-               
+
                if (rectify) {
                        if (fabs (min) > fabs (max)) {
                                max = fabs (min);
                if (rectify) {
                        if (fabs (min) > fabs (max)) {
                                max = fabs (min);
-                       } 
-               } 
-               
+                       }
+               }
+
                yoff = origin - (waveview->half_height * max) + 0.5;
                yoff = origin - (waveview->half_height * max) + 0.5;
-               
+
                if (xoff == ulx) {
                        /* first point */
                        cairo_move_to (cr, xoff+0.5, yoff);
                if (xoff == ulx) {
                        /* first point */
                        cairo_move_to (cr, xoff+0.5, yoff);
@@ -1769,9 +2342,9 @@ gnome_canvas_waveview_draw (GnomeCanvasItem *item,
        }
 
        /* from the final top point, move out of the clip zone */
        }
 
        /* from the final top point, move out of the clip zone */
-       
+
        cairo_line_to (cr, xoff + 10, yoff);
        cairo_line_to (cr, xoff + 10, yoff);
-       
+
        /* now draw the bottom half */
 
        for (--xoff, --cache_index; xoff >= ulx; --xoff) {
        /* now draw the bottom half */
 
        for (--xoff, --cache_index; xoff >= ulx; --xoff) {
@@ -1792,23 +2365,23 @@ gnome_canvas_waveview_draw (GnomeCanvasItem *item,
        /* from the final lower point, move out of the clip zone */
 
        cairo_line_to (cr, xoff - 10, yoff);
        /* from the final lower point, move out of the clip zone */
 
        cairo_line_to (cr, xoff - 10, yoff);
-       
+
        /* close path to fill */
 
        cairo_close_path (cr);
 
        /* fill and stroke */
 
        /* close path to fill */
 
        cairo_close_path (cr);
 
        /* fill and stroke */
 
-       cairo_set_source_rgba (cr, 
-                              (waveview->fill_r/255.0), 
-                              (waveview->fill_g/255.0), 
-                              (waveview->fill_b/255.0), 
+       cairo_set_source_rgba (cr,
+                              (waveview->fill_r/255.0),
+                              (waveview->fill_g/255.0),
+                              (waveview->fill_b/255.0),
                               (waveview->fill_a/255.0));
        cairo_fill_preserve (cr);
                               (waveview->fill_a/255.0));
        cairo_fill_preserve (cr);
-       cairo_set_source_rgba (cr, 
-                              (waveview->wave_r/255.0), 
-                              (waveview->wave_g/255.0), 
-                              (waveview->wave_b/255.0), 
+       cairo_set_source_rgba (cr,
+                              (waveview->wave_r/255.0),
+                              (waveview->wave_g/255.0),
+                              (waveview->wave_b/255.0),
                               (waveview->wave_a/255.0));
        cairo_stroke (cr);
 
                               (waveview->wave_a/255.0));
        cairo_stroke (cr);
 
@@ -1825,13 +2398,13 @@ gnome_canvas_waveview_draw (GnomeCanvasItem *item,
                        cairo_line_to (cr, xoff, yoff1 + clip_length);
                        cairo_stroke (cr);
                }
                        cairo_line_to (cr, xoff, yoff1 + clip_length);
                        cairo_stroke (cr);
                }
-               
+
                if (clip_min) {
                        cairo_move_to (cr, xoff, yoff2);
                        cairo_line_to (cr, xoff, yoff2 - clip_length);
                        cairo_stroke (cr);
                }
                if (clip_min) {
                        cairo_move_to (cr, xoff, yoff2);
                        cairo_line_to (cr, xoff, yoff2 - clip_length);
                        cairo_stroke (cr);
                }
-               
+
 #endif
 
 static void
 #endif
 
 static void
@@ -1854,14 +2427,21 @@ gnome_canvas_waveview_bounds (GnomeCanvasItem *item, double *x1, double *y1, dou
        gnome_canvas_item_i2w (item, &x, &y);
        gnome_canvas_w2c_d (GNOME_CANVAS(item->canvas), x, y, &c, &d);
        printf ("item bounds now (%g,%g),(%g,%g)\n", a, b, c, d);
        gnome_canvas_item_i2w (item, &x, &y);
        gnome_canvas_w2c_d (GNOME_CANVAS(item->canvas), x, y, &c, &d);
        printf ("item bounds now (%g,%g),(%g,%g)\n", a, b, c, d);
-#endif         
+#endif
 
 }
 
 static double
 gnome_canvas_waveview_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item)
 {
 
 }
 
 static double
 gnome_canvas_waveview_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item)
 {
-       /* XXX for now, point is never inside the wave 
+       (void) item;
+       (void) x;
+       (void) y;
+       (void) cx;
+       (void) cy;
+       (void) actual_item;
+
+       /* XXX for now, point is never inside the wave
        GnomeCanvasWaveView *waveview;
        double x1, y1, x2, y2;
        double dx, dy;
        GnomeCanvasWaveView *waveview;
        double x1, y1, x2, y2;
        double dx, dy;
@@ -1879,7 +2459,7 @@ gnome_canvas_waveview_point (GnomeCanvasItem *item, double x, double y, int cx,
        gnome_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2);
 
        /* Is point inside rectangle */
        gnome_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2);
 
        /* Is point inside rectangle */
-       
+
        if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
                return 0.0;
        }
        if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
                return 0.0;
        }