Chris@1030
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@1030
|
2
|
Chris@1030
|
3 /*
|
Chris@1030
|
4 Sonic Visualiser
|
Chris@1030
|
5 An audio file viewer and annotation editor.
|
Chris@1030
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@1030
|
7
|
Chris@1030
|
8 This program is free software; you can redistribute it and/or
|
Chris@1030
|
9 modify it under the terms of the GNU General Public License as
|
Chris@1030
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@1030
|
11 License, or (at your option) any later version. See the file
|
Chris@1030
|
12 COPYING included with this distribution for more information.
|
Chris@1030
|
13 */
|
Chris@1030
|
14
|
Chris@1030
|
15 #ifndef SCROLLABLE_IMAGE_CACHE_H
|
Chris@1030
|
16 #define SCROLLABLE_IMAGE_CACHE_H
|
Chris@1030
|
17
|
Chris@1030
|
18 #include "base/BaseTypes.h"
|
Chris@1030
|
19
|
Chris@1077
|
20 #include "LayerGeometryProvider.h"
|
Chris@1030
|
21
|
Chris@1030
|
22 #include <QImage>
|
Chris@1030
|
23 #include <QRect>
|
Chris@1030
|
24 #include <QPainter>
|
Chris@1030
|
25
|
Chris@1030
|
26 /**
|
Chris@1118
|
27 * A cached image for a view that scrolls horizontally, such as a
|
Chris@1030
|
28 * spectrogram. The cache object holds an image, reports the size of
|
Chris@1030
|
29 * the image (likely the same as the underlying view, but it's the
|
Chris@1030
|
30 * caller's responsibility to set the size appropriately), can scroll
|
Chris@1030
|
31 * the image, and can report and update which contiguous horizontal
|
Chris@1030
|
32 * range of the image is valid.
|
Chris@1030
|
33 *
|
Chris@1030
|
34 * The only way to *update* the valid area in a cache is to draw to it
|
Chris@1030
|
35 * using the drawImage call.
|
Chris@1030
|
36 */
|
Chris@1030
|
37 class ScrollableImageCache
|
Chris@1030
|
38 {
|
Chris@1030
|
39 public:
|
Chris@1090
|
40 ScrollableImageCache() :
|
Chris@1118
|
41 m_validLeft(0),
|
Chris@1118
|
42 m_validWidth(0),
|
Chris@1030
|
43 m_startFrame(0),
|
Chris@1030
|
44 m_zoomLevel(0)
|
Chris@1030
|
45 {}
|
Chris@1030
|
46
|
Chris@1030
|
47 void invalidate() {
|
Chris@1118
|
48 m_validWidth = 0;
|
Chris@1030
|
49 }
|
Chris@1030
|
50
|
Chris@1030
|
51 bool isValid() const {
|
Chris@1118
|
52 return m_validWidth > 0;
|
Chris@1030
|
53 }
|
Chris@1030
|
54
|
Chris@1030
|
55 QSize getSize() const {
|
Chris@1030
|
56 return m_image.size();
|
Chris@1030
|
57 }
|
Chris@1118
|
58
|
Chris@1118
|
59 /**
|
Chris@1118
|
60 * Set the size of the cache. If the new size differs from the
|
Chris@1118
|
61 * current size, the cache is invalidated.
|
Chris@1118
|
62 */
|
Chris@1030
|
63 void resize(QSize newSize) {
|
Chris@1079
|
64 if (getSize() != newSize) {
|
Chris@1079
|
65 m_image = QImage(newSize, QImage::Format_ARGB32_Premultiplied);
|
Chris@1079
|
66 invalidate();
|
Chris@1079
|
67 }
|
Chris@1030
|
68 }
|
Chris@1030
|
69
|
Chris@1030
|
70 int getValidLeft() const {
|
Chris@1118
|
71 return m_validLeft;
|
Chris@1030
|
72 }
|
Chris@1030
|
73
|
Chris@1030
|
74 int getValidWidth() const {
|
Chris@1118
|
75 return m_validWidth;
|
Chris@1030
|
76 }
|
Chris@1030
|
77
|
Chris@1030
|
78 int getValidRight() const {
|
Chris@1118
|
79 return m_validLeft + m_validWidth;
|
Chris@1030
|
80 }
|
Chris@1030
|
81
|
Chris@1030
|
82 QRect getValidArea() const {
|
Chris@1118
|
83 return QRect(m_validLeft, 0, m_validWidth, m_image.height());
|
Chris@1030
|
84 }
|
Chris@1030
|
85
|
Chris@1030
|
86 int getZoomLevel() const {
|
Chris@1030
|
87 return m_zoomLevel;
|
Chris@1030
|
88 }
|
Chris@1118
|
89
|
Chris@1118
|
90 /**
|
Chris@1118
|
91 * Set the zoom level. If the new zoom level differs from the
|
Chris@1118
|
92 * current one, the cache is invalidated. (Determining whether to
|
Chris@1118
|
93 * invalidate the cache here is the only thing the zoom level is
|
Chris@1118
|
94 * used for.)
|
Chris@1118
|
95 */
|
Chris@1031
|
96 void setZoomLevel(int zoom) {
|
Chris@1079
|
97 if (m_zoomLevel != zoom) {
|
Chris@1079
|
98 m_zoomLevel = zoom;
|
Chris@1079
|
99 invalidate();
|
Chris@1079
|
100 }
|
Chris@1031
|
101 }
|
Chris@1030
|
102
|
Chris@1030
|
103 sv_frame_t getStartFrame() const {
|
Chris@1030
|
104 return m_startFrame;
|
Chris@1030
|
105 }
|
Chris@1031
|
106
|
Chris@1031
|
107 /**
|
Chris@1118
|
108 * Set the start frame. If the new start frame differs from the
|
Chris@1118
|
109 * current one, the cache is invalidated. To scroll, i.e. to set
|
Chris@1118
|
110 * the start frame while retaining cache validity where possible,
|
Chris@1118
|
111 * use scrollTo() instead.
|
Chris@1031
|
112 */
|
Chris@1031
|
113 void setStartFrame(sv_frame_t frame) {
|
Chris@1079
|
114 if (m_startFrame != frame) {
|
Chris@1079
|
115 m_startFrame = frame;
|
Chris@1079
|
116 invalidate();
|
Chris@1079
|
117 }
|
Chris@1030
|
118 }
|
Chris@1030
|
119
|
Chris@1030
|
120 const QImage &getImage() const {
|
Chris@1030
|
121 return m_image;
|
Chris@1030
|
122 }
|
Chris@1030
|
123
|
Chris@1031
|
124 /**
|
Chris@1090
|
125 * Set the new start frame for the cache, according to the
|
Chris@1090
|
126 * geometry of the supplied LayerGeometryProvider, if possible
|
Chris@1090
|
127 * also moving along any existing valid data within the cache so
|
Chris@1090
|
128 * that it continues to be valid for the new start frame.
|
Chris@1031
|
129 */
|
Chris@1113
|
130 void scrollTo(const LayerGeometryProvider *v, sv_frame_t newStartFrame);
|
Chris@1030
|
131
|
Chris@1031
|
132 /**
|
Chris@1031
|
133 * Take a left coordinate and width describing a region, and
|
Chris@1031
|
134 * adjust them so that they are contiguous with the cache valid
|
Chris@1031
|
135 * region and so that the union of the adjusted region with the
|
Chris@1081
|
136 * cache valid region contains the supplied region. Does not
|
Chris@1081
|
137 * modify anything about the cache, only about the arguments.
|
Chris@1031
|
138 */
|
Chris@1031
|
139 void adjustToTouchValidArea(int &left, int &width,
|
Chris@1031
|
140 bool &isLeftOfValidArea) const;
|
Chris@1081
|
141
|
Chris@1031
|
142 /**
|
Chris@1031
|
143 * Draw from an image onto the cache. The supplied image must have
|
Chris@1031
|
144 * the same height as the cache and the full height is always
|
Chris@1031
|
145 * drawn. The left and width parameters determine the target
|
Chris@1031
|
146 * region of the cache, the imageLeft and imageWidth parameters
|
Chris@1031
|
147 * the source region of the image.
|
Chris@1031
|
148 */
|
Chris@1030
|
149 void drawImage(int left,
|
Chris@1030
|
150 int width,
|
Chris@1030
|
151 QImage image,
|
Chris@1030
|
152 int imageLeft,
|
Chris@1031
|
153 int imageWidth);
|
Chris@1030
|
154
|
Chris@1030
|
155 private:
|
Chris@1030
|
156 QImage m_image;
|
Chris@1118
|
157 int m_validLeft;
|
Chris@1118
|
158 int m_validWidth;
|
Chris@1030
|
159 sv_frame_t m_startFrame;
|
Chris@1030
|
160 int m_zoomLevel;
|
Chris@1030
|
161 };
|
Chris@1030
|
162
|
Chris@1030
|
163 #endif
|