view layer/ScrollableImageCache.h @ 1064:77564d4fff43 spectrogram-minor-refactor

Extend column logic to peak frequency display as well, and correct some scopes according to whether values are per source column or per target pixel
author Chris Cannam
date Mon, 20 Jun 2016 12:00:32 +0100
parents 55ac6ac1982e
children 5144d7185fb5
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

/*
    Sonic Visualiser
    An audio file viewer and annotation editor.
    Centre for Digital Music, Queen Mary, University of London.
    
    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 the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.  See the file
    COPYING included with this distribution for more information.
*/

#ifndef SCROLLABLE_IMAGE_CACHE_H
#define SCROLLABLE_IMAGE_CACHE_H

#include "base/BaseTypes.h"

#include "view/LayerGeometryProvider.h"

#include <QImage>
#include <QRect>
#include <QPainter>

/**
 * A cached image for a view that scrolls horizontally, primarily the
 * spectrogram. The cache object holds an image, reports the size of
 * the image (likely the same as the underlying view, but it's the
 * caller's responsibility to set the size appropriately), can scroll
 * the image, and can report and update which contiguous horizontal
 * range of the image is valid.
 *
 * The only way to *update* the valid area in a cache is to draw to it
 * using the drawImage call.
 */
class ScrollableImageCache
{
public:
    ScrollableImageCache(const LayerGeometryProvider *v = 0) :
	m_v(v),
	m_left(0),
	m_width(0),
	m_startFrame(0),
	m_zoomLevel(0)
    {}

    void invalidate() {
	m_width = 0;
    }
    
    bool isValid() const {
	return m_width > 0;
    }

    QSize getSize() const {
	return m_image.size();
    }
    
    void resize(QSize newSize) {
	m_image = QImage(newSize, QImage::Format_ARGB32_Premultiplied);
	invalidate();
    }
	
    int getValidLeft() const {
	return m_left;
    }
    
    int getValidWidth() const {
	return m_width;
    }

    int getValidRight() const {
	return m_left + m_width;
    }

    QRect getValidArea() const {
	return QRect(m_left, 0, m_width, m_image.height());
    }
    
    int getZoomLevel() const {
	return m_zoomLevel;
    }
    
    void setZoomLevel(int zoom) {
	m_zoomLevel = zoom;
	invalidate();
    }

    sv_frame_t getStartFrame() const {
	return m_startFrame;
    }

    /**
     * Set the start frame and invalidate the cache. To scroll,
     * i.e. to set the start frame while retaining cache validity
     * where possible, use scrollTo() instead.
     */
    void setStartFrame(sv_frame_t frame) {
	m_startFrame = frame;
	invalidate();
    }
    
    const QImage &getImage() const {
	return m_image;
    }

    /**
     * Set the new start frame for the cache, if possible also moving
     * along any existing valid data within the cache so that it
     * continues to be valid for the new start frame.
     */
    void scrollTo(sv_frame_t newStartFrame);

    /**
     * Take a left coordinate and width describing a region, and
     * adjust them so that they are contiguous with the cache valid
     * region and so that the union of the adjusted region with the
     * cache valid region contains the supplied region.
     */
    void adjustToTouchValidArea(int &left, int &width,
				bool &isLeftOfValidArea) const;
    /**
     * Draw from an image onto the cache. The supplied image must have
     * the same height as the cache and the full height is always
     * drawn. The left and width parameters determine the target
     * region of the cache, the imageLeft and imageWidth parameters
     * the source region of the image.
     */
    void drawImage(int left,
		   int width,
		   QImage image,
		   int imageLeft,
		   int imageWidth);
    
private:
    const LayerGeometryProvider *m_v;
    QImage m_image;
    int m_left;  // of valid region
    int m_width; // of valid region
    sv_frame_t m_startFrame;
    int m_zoomLevel;
};

#endif