diff layer/SpectrogramLayer.cpp @ 331:d2d2521a6c7e

* Some fixes to cache repainting strategy -- should make things a little quicker, but some glitches remain
author Chris Cannam
date Mon, 19 Nov 2007 15:50:14 +0000
parents 29fcf125f98b
children 0a74248af622
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp	Sun Nov 11 21:47:19 2007 +0000
+++ b/layer/SpectrogramLayer.cpp	Mon Nov 19 15:50:14 2007 +0000
@@ -901,6 +901,11 @@
 {
     if (dormant) {
 
+#ifdef DEBUG_SPECTROGRAM_REPAINT
+        std::cerr << "SpectrogramLayer::setLayerDormant(" << dormant << ")"
+                  << std::endl;
+#endif
+
         if (isLayerDormant(v)) {
             return;
         }
@@ -1754,33 +1759,27 @@
                     dx > -cache.pixmap.width() &&
                     dx <  cache.pixmap.width()) {
 
-#if defined(Q_WS_WIN32) || defined(Q_WS_MAC)
-		    // Copying a pixmap to itself doesn't work
-		    // properly on Windows or Mac (it only works when
-		    // moving in one direction).
-
-		    //!!! Need a utility function for this
-
-		    static QPixmap *tmpPixmap = 0;
-		    if (!tmpPixmap ||
-			tmpPixmap->width() != cache.pixmap.width() ||
-			tmpPixmap->height() != cache.pixmap.height()) {
-			delete tmpPixmap;
-			tmpPixmap = new QPixmap(cache.pixmap.width(),
-						cache.pixmap.height());
-		    }
-		    QPainter cachePainter;
-		    cachePainter.begin(tmpPixmap);
-		    cachePainter.drawPixmap(0, 0, cache.pixmap);
-		    cachePainter.end();
-		    cachePainter.begin(&cache.pixmap);
-		    cachePainter.drawPixmap(dx, 0, *tmpPixmap);
-		    cachePainter.end();
-#else
-		    QPainter cachePainter(&cache.pixmap);
-		    cachePainter.drawPixmap(dx, 0, cache.pixmap);
-		    cachePainter.end();
-#endif
+                    QPixmap tmp = cache.pixmap;
+                    QPainter cachePainter(&cache.pixmap);
+                    if (dx < 0) {
+                        cachePainter.drawPixmap
+                            (QRect(0, 0,
+                                   cache.pixmap.width() + dx,
+                                   cache.pixmap.height()),
+                             tmp,
+                             QRect(-dx, 0,
+                                   cache.pixmap.width() + dx,
+                                   cache.pixmap.height()));
+                    } else {
+                        cachePainter.drawPixmap
+                            (QRect(dx, 0,
+                                   cache.pixmap.width() - dx,
+                                   cache.pixmap.height()),
+                             tmp,
+                             QRect(0, 0,
+                                   cache.pixmap.width() - dx,
+                                   cache.pixmap.height()));
+                    }
 
                     int px = cache.validArea.x();
                     int pw = cache.validArea.width();
@@ -1808,10 +1807,24 @@
                         QRect(px, cache.validArea.y(),
                               pw, cache.validArea.height());
 
+#ifdef DEBUG_SPECTROGRAM_REPAINT
+                    std::cerr << "valid area now "
+                              << px << "," << cache.validArea.y()
+                              << " " << pw << "x" << cache.validArea.height()
+                              << std::endl;
+#endif
+
 		    paint.drawPixmap(rect & cache.validArea,
                                      cache.pixmap,
                                      rect & cache.validArea);
-		}
+
+                } else if (dx != 0) {
+
+                    // we scrolled too far to be of use
+
+                    cache.validArea = QRect();
+                    recreateWholePixmapCache = true;
+                }
 	    }
 	} else {
 #ifdef DEBUG_SPECTROGRAM_REPAINT
@@ -1837,7 +1850,10 @@
 #ifdef DEBUG_SPECTROGRAM_REPAINT
         std::cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl;
 #endif
-        recreateWholePixmapCache = true;
+        if (m_normalizeVisibleArea) {
+            cache.validArea = QRect();
+            recreateWholePixmapCache = true;
+        }
     } else {
 #ifdef DEBUG_SPECTROGRAM_REPAINT
         std::cerr << "No change in magnitude range [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl;
@@ -1887,33 +1903,38 @@
 
     if (cache.validArea.width() > 0) {
 
+        // If part of the cache is known to be valid, select a strip
+        // immediately to left or right of the valid part
+
         int vx0 = 0, vx1 = 0;
         vx0 = cache.validArea.x();
         vx1 = cache.validArea.x() + cache.validArea.width();
         
 #ifdef DEBUG_SPECTROGRAM_REPAINT
         std::cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << ", paintBlockWidth " << paintBlockWidth << std::endl;
-#endif            
+#endif         
         if (x0 < vx0) {
             if (x0 + paintBlockWidth < vx0) {
                 x0 = vx0 - paintBlockWidth;
+            }
+            x1 = vx0;
+        } else if (x0 >= vx1) {
+            x0 = vx1;
+            if (x1 > x0 + paintBlockWidth) {
+                x1 = x0 + paintBlockWidth;
+            }
+        } else {
+            // x0 is within the valid area
+            if (x1 > vx1) {
+                x0 = vx1;
+                if (x0 + paintBlockWidth < x1) {
+                    x1 = x0 + paintBlockWidth;
+                }
             } else {
-                x0 = 0;
-            }
-        } else if (x0 > vx1) {
-            x0 = vx1;
-        }
-            
-        if (x1 < vx0) {
-            x1 = vx0;
-        } else if (x1 > vx1) {
-            if (vx1 + paintBlockWidth < x1) {
-                x1 = vx1 + paintBlockWidth;
-            } else {
-                x1 = v->width();
+                x1 = x0; // it's all valid, paint nothing
             }
         }
-            
+         
         cache.validArea = QRect
             (std::min(vx0, x0), cache.validArea.y(),
              std::max(vx1 - std::min(vx0, x0),
@@ -2029,9 +2050,22 @@
 
     bool runOutOfData = false;
 
+    if (w == 0) {
+        std::cerr << "*** NOTE: w == 0" << std::endl;
+    }
+
+#ifdef DEBUG_SPECTROGRAM_REPAINT
+    size_t pixels = 0;
+#endif
+
     for (int x = 0; x < w; ++x) {
 
-        if (runOutOfData) break;
+        if (runOutOfData) {
+#ifdef DEBUG_SPECTROGRAM_REPAINT
+            std::cerr << "Run out of data -- dropping out of loop" << std::endl;
+#endif
+            break;
+        }
 
 	for (int y = 0; y < h; ++y) {
 	    ymag[y] = 0.f;
@@ -2050,6 +2084,9 @@
 
 	if (s1i >= int(fft->getWidth())) {
 	    if (s0i >= int(fft->getWidth())) {
+#ifdef DEBUG_SPECTROGRAM_REPAINT
+                std::cerr << "Column " << s0i << " out of range" << std::endl;
+#endif
 		continue;
 	    } else {
 		s1i = s0i;
@@ -2218,10 +2255,17 @@
 		QColor c = m_palette.getColour(pixel);
 		m_drawBuffer.setPixel(x, y,
                                       qRgb(c.red(), c.green(), c.blue()));
+#ifdef DEBUG_SPECTROGRAM_REPAINT
+                ++pixels;
+#endif
 	    }
 	}
     }
 
+#ifdef DEBUG_SPECTROGRAM_REPAINT
+    std::cerr << pixels << " pixels drawn" << std::endl;
+#endif
+
     if (overallMagChanged) {
         m_viewMags[v] = overallMag;
 #ifdef DEBUG_SPECTROGRAM_REPAINT
@@ -2235,33 +2279,40 @@
 
     Profiler profiler2("SpectrogramLayer::paint: draw image", true);
 
+    if (w > 0) {
 #ifdef DEBUG_SPECTROGRAM_REPAINT
-    std::cerr << "Painting " << w << "x" << rect.height()
-              << " from draw buffer at " << 0 << "," << rect.y()
-              << " to window at " << x0 << "," << rect.y() << std::endl;
+        std::cerr << "Painting " << w << "x" << rect.height()
+                  << " from draw buffer at " << 0 << "," << rect.y()
+                  << " to window at " << x0 << "," << rect.y() << std::endl;
 #endif
 
-    paint.drawImage(x0, rect.y(), m_drawBuffer, 0, rect.y(), w, rect.height());
+        paint.drawImage(x0, rect.y(), m_drawBuffer,
+                        0, rect.y(), w, rect.height());
+    }
 
     if (recreateWholePixmapCache) {
+        std::cerr << "Recreating pixmap cache: width = " << v->width()
+                  << ", height = " << h << std::endl;
 	cache.pixmap = QPixmap(v->width(), h);
     }
 
+    if (w > 0) {
 #ifdef DEBUG_SPECTROGRAM_REPAINT
-    std::cerr << "Painting " << w << "x" << h
-              << " from draw buffer at " << 0 << "," << 0
-              << " to cache at " << x0 << "," << 0 << std::endl;
+        std::cerr << "Painting " << w << "x" << h
+                  << " from draw buffer at " << 0 << "," << 0
+                  << " to cache at " << x0 << "," << 0 << std::endl;
 #endif
 
-    QPainter cachePainter(&cache.pixmap);
-    cachePainter.drawImage(x0, 0, m_drawBuffer, 0, 0, w, h);
-    cachePainter.end();
+        QPainter cachePainter(&cache.pixmap);
+        cachePainter.drawImage(x0, 0, m_drawBuffer, 0, 0, w, h);
+        cachePainter.end();
+    }
+
+    cache.startFrame = startFrame;
+    cache.zoomLevel = zoomLevel;
 
     if (!m_normalizeVisibleArea || !overallMagChanged) {
     
-        cache.startFrame = startFrame;
-        cache.zoomLevel = zoomLevel;
-
         if (cache.validArea.x() > 0) {
 #ifdef DEBUG_SPECTROGRAM_REPAINT
             std::cerr << "SpectrogramLayer::paint() updating left (0, "
@@ -2288,6 +2339,7 @@
         }
     } else {
         // overallMagChanged
+        std::cerr << "\noverallMagChanged - updating all\n" << std::endl;
         cache.validArea = QRect();
         v->update();
     }