File: ScrollableImageCache.h

package info (click to toggle)
sonic-visualiser 5.2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,744 kB
  • sloc: cpp: 158,888; ansic: 11,920; sh: 1,785; makefile: 517; xml: 64; perl: 31
file content (164 lines) | stat: -rw-r--r-- 4,850 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* -*- 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 "LayerGeometryProvider.h"

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

namespace sv {

/**
 * A cached image for a view that scrolls horizontally, such as a
 * 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();
    ~ScrollableImageCache();

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

    QSize getSize() const {
        return m_image.size();
    }

    /**
     * Set the size of the cache. If the new size differs from the
     * current size, the cache is invalidated.
     */
    void resize(QSize newSize) {
        if (getSize() != newSize) {
            m_image = QImage(newSize, QImage::Format_ARGB32_Premultiplied);
            invalidate();
        }
    }
        
    int getValidLeft() const {
        return m_validLeft;
    }
    
    int getValidWidth() const {
        return m_validWidth;
    }

    int getValidRight() const {
        return m_validLeft + m_validWidth;
    }

    QRect getValidArea() const {
        return QRect(m_validLeft, 0, m_validWidth, m_image.height());
    }
    
    ZoomLevel getZoomLevel() const {
        return m_zoomLevel;
    }

    /**
     * Set the zoom level. If the new zoom level differs from the
     * current one, the cache is invalidated. Note that determining
     * whether to invalidate the cache is the only thing the zoom
     * level is used for, so you should use raw unscaled zoom values
     * (in order to reflect changes correctly) rather than values
     * properly scaled for hi-dpi.
     */
    void setZoomLevel(ZoomLevel zoom) {
        using namespace std::rel_ops;
        if (m_zoomLevel != zoom) {
            m_zoomLevel = zoom;
            invalidate();
        }
    }

    sv_frame_t getStartFrame() const {
        return m_startFrame;
    }

    /**
     * Set the start frame. If the new start frame differs from the
     * current one, the cache is invalidated. To scroll, i.e. to set
     * the start frame while retaining cache validity where possible,
     * use scrollTo() instead.
     */
    void setStartFrame(sv_frame_t frame) {
        if (m_startFrame != frame) {
            m_startFrame = frame;
            invalidate();
        }
    }
    
    const QImage &getImage() const {
        return m_image;
    }

    /**
     * Set the new start frame for the cache, according to the
     * geometry of the supplied LayerGeometryProvider, 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(const LayerGeometryProvider *v, 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.  Does not
     * modify anything about the cache, only about the arguments.
     */
    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:
    QImage m_image;
    int m_validLeft;
    int m_validWidth;
    sv_frame_t m_startFrame;
    ZoomLevel m_zoomLevel;
};

} // end namespace sv

#endif