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@1030
|
20 #include "view/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@1030
|
27 * A cached image for a view that scrolls horizontally, primarily the
|
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@1030
|
40 ScrollableImageCache(const LayerGeometryProvider *v = 0) :
|
Chris@1030
|
41 m_v(v),
|
Chris@1030
|
42 m_left(0),
|
Chris@1030
|
43 m_width(0),
|
Chris@1030
|
44 m_startFrame(0),
|
Chris@1030
|
45 m_zoomLevel(0)
|
Chris@1030
|
46 {}
|
Chris@1030
|
47
|
Chris@1030
|
48 void invalidate() {
|
Chris@1030
|
49 m_width = 0;
|
Chris@1030
|
50 }
|
Chris@1030
|
51
|
Chris@1030
|
52 bool isValid() const {
|
Chris@1030
|
53 return m_width > 0;
|
Chris@1030
|
54 }
|
Chris@1030
|
55
|
Chris@1030
|
56 QSize getSize() const {
|
Chris@1030
|
57 return m_image.size();
|
Chris@1030
|
58 }
|
Chris@1030
|
59
|
Chris@1030
|
60 void resize(QSize newSize) {
|
Chris@1030
|
61 m_image = QImage(newSize, QImage::Format_ARGB32_Premultiplied);
|
Chris@1030
|
62 invalidate();
|
Chris@1030
|
63 }
|
Chris@1030
|
64
|
Chris@1030
|
65 int getValidLeft() const {
|
Chris@1030
|
66 return m_left;
|
Chris@1030
|
67 }
|
Chris@1030
|
68
|
Chris@1030
|
69 int getValidWidth() const {
|
Chris@1030
|
70 return m_width;
|
Chris@1030
|
71 }
|
Chris@1030
|
72
|
Chris@1030
|
73 int getValidRight() const {
|
Chris@1030
|
74 return m_left + m_width;
|
Chris@1030
|
75 }
|
Chris@1030
|
76
|
Chris@1030
|
77 QRect getValidArea() const {
|
Chris@1030
|
78 return QRect(m_left, 0, m_width, m_image.height());
|
Chris@1030
|
79 }
|
Chris@1030
|
80
|
Chris@1030
|
81 int getZoomLevel() const {
|
Chris@1030
|
82 return m_zoomLevel;
|
Chris@1030
|
83 }
|
Chris@1031
|
84
|
Chris@1031
|
85 void setZoomLevel(int zoom) {
|
Chris@1031
|
86 m_zoomLevel = zoom;
|
Chris@1031
|
87 invalidate();
|
Chris@1031
|
88 }
|
Chris@1030
|
89
|
Chris@1030
|
90 sv_frame_t getStartFrame() const {
|
Chris@1030
|
91 return m_startFrame;
|
Chris@1030
|
92 }
|
Chris@1031
|
93
|
Chris@1031
|
94 /**
|
Chris@1031
|
95 * Set the start frame and invalidate the cache. To scroll,
|
Chris@1031
|
96 * i.e. to set the start frame while retaining cache validity
|
Chris@1031
|
97 * where possible, use scrollTo() instead.
|
Chris@1031
|
98 */
|
Chris@1031
|
99 void setStartFrame(sv_frame_t frame) {
|
Chris@1031
|
100 m_startFrame = frame;
|
Chris@1030
|
101 invalidate();
|
Chris@1030
|
102 }
|
Chris@1030
|
103
|
Chris@1030
|
104 const QImage &getImage() const {
|
Chris@1030
|
105 return m_image;
|
Chris@1030
|
106 }
|
Chris@1030
|
107
|
Chris@1031
|
108 /**
|
Chris@1031
|
109 * Set the new start frame for the cache, if possible also moving
|
Chris@1031
|
110 * along any existing valid data within the cache so that it
|
Chris@1031
|
111 * continues to be valid for the new start frame.
|
Chris@1031
|
112 */
|
Chris@1031
|
113 void scrollTo(sv_frame_t newStartFrame);
|
Chris@1030
|
114
|
Chris@1031
|
115 /**
|
Chris@1031
|
116 * Take a left coordinate and width describing a region, and
|
Chris@1031
|
117 * adjust them so that they are contiguous with the cache valid
|
Chris@1031
|
118 * region and so that the union of the adjusted region with the
|
Chris@1031
|
119 * cache valid region contains the supplied region.
|
Chris@1031
|
120 */
|
Chris@1031
|
121 void adjustToTouchValidArea(int &left, int &width,
|
Chris@1031
|
122 bool &isLeftOfValidArea) const;
|
Chris@1031
|
123 /**
|
Chris@1031
|
124 * Draw from an image onto the cache. The supplied image must have
|
Chris@1031
|
125 * the same height as the cache and the full height is always
|
Chris@1031
|
126 * drawn. The left and width parameters determine the target
|
Chris@1031
|
127 * region of the cache, the imageLeft and imageWidth parameters
|
Chris@1031
|
128 * the source region of the image.
|
Chris@1031
|
129 */
|
Chris@1030
|
130 void drawImage(int left,
|
Chris@1030
|
131 int width,
|
Chris@1030
|
132 QImage image,
|
Chris@1030
|
133 int imageLeft,
|
Chris@1031
|
134 int imageWidth);
|
Chris@1030
|
135
|
Chris@1030
|
136 private:
|
Chris@1030
|
137 const LayerGeometryProvider *m_v;
|
Chris@1030
|
138 QImage m_image;
|
Chris@1030
|
139 int m_left; // of valid region
|
Chris@1030
|
140 int m_width; // of valid region
|
Chris@1030
|
141 sv_frame_t m_startFrame;
|
Chris@1030
|
142 int m_zoomLevel;
|
Chris@1030
|
143 };
|
Chris@1030
|
144
|
Chris@1030
|
145 #endif
|