comparison layer/ScrollableImageCache.cpp @ 1035:6d084d6d5015 spectrogram-minor-refactor

*Really* add overlooked file!
author Chris Cannam
date Tue, 02 Feb 2016 10:44:07 +0000
parents
children bc9b4a163926
comparison
equal deleted inserted replaced
1031:55ac6ac1982e 1035:6d084d6d5015
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information.
13 */
14
15 #include "ScrollableImageCache.h"
16
17 #include <iostream>
18 using namespace std;
19
20 #define DEBUG_SCROLLABLE_IMAGE_CACHE 1
21
22 void
23 ScrollableImageCache::scrollTo(sv_frame_t newStartFrame)
24 {
25 if (!m_v) throw std::logic_error("ScrollableImageCache: not associated with a LayerGeometryProvider");
26
27 int dx = (m_v->getXForFrame(m_startFrame) -
28 m_v->getXForFrame(newStartFrame));
29
30 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE
31 cerr << "ScrollableImageCache::scrollTo: start frame " << m_startFrame
32 << " -> " << newStartFrame << ", dx = " << dx << endl;
33 #endif
34
35 m_startFrame = newStartFrame;
36
37 if (!isValid()) {
38 return;
39 }
40
41 int w = m_image.width();
42
43 if (dx == 0) {
44 // haven't moved
45 return;
46 }
47
48 if (dx <= -w || dx >= w) {
49 // scrolled entirely off
50 invalidate();
51 return;
52 }
53
54 // dx is in range, cache is scrollable
55
56 int dxp = dx;
57 if (dxp < 0) dxp = -dxp;
58
59 int copylen = (w - dxp) * int(sizeof(QRgb));
60 for (int y = 0; y < m_image.height(); ++y) {
61 QRgb *line = (QRgb *)m_image.scanLine(y);
62 if (dx < 0) {
63 memmove(line, line + dxp, copylen);
64 } else {
65 memmove(line + dxp, line, copylen);
66 }
67 }
68
69 // update valid area
70
71 int px = m_left;
72 int pw = m_width;
73
74 px += dx;
75
76 if (dx < 0) {
77 // we scrolled left
78 if (px < 0) {
79 pw += px;
80 px = 0;
81 if (pw < 0) {
82 pw = 0;
83 }
84 }
85 } else {
86 // we scrolled right
87 if (px + pw > w) {
88 pw = w - px;
89 if (pw < 0) {
90 pw = 0;
91 }
92 }
93 }
94
95 m_left = px;
96 m_width = pw;
97 }
98
99 void
100 ScrollableImageCache::adjustToTouchValidArea(int &left, int &width,
101 bool &isLeftOfValidArea) const
102 {
103 if (left < m_left) {
104 isLeftOfValidArea = true;
105 if (left + width < m_left + m_width) {
106 width = m_left - left;
107 }
108 } else {
109 isLeftOfValidArea = false;
110 width = left + width - (m_left + m_width);
111 left = m_left + m_width;
112 if (width < 0) width = 0;
113 }
114 }
115
116 void
117 ScrollableImageCache::drawImage(int left,
118 int width,
119 QImage image,
120 int imageLeft,
121 int imageWidth)
122 {
123 if (image.height() != m_image.height()) {
124 cerr << "ScrollableImageCache::drawImage: ERROR: Supplied image height "
125 << image.height() << " does not match cache height "
126 << m_image.height() << endl;
127 throw std::logic_error("Image height must match cache height in ScrollableImageCache::drawImage");
128 }
129 if (left < 0 || width < 0 || left + width > m_image.width()) {
130 cerr << "ScrollableImageCache::drawImage: ERROR: Target area (left = "
131 << left << ", width = " << width << ") out of bounds for cache of "
132 << "width " << m_image.width() << endl;
133 throw std::logic_error("Target area out of bounds in ScrollableImageCache::drawImage");
134 }
135 if (imageLeft < 0 || imageWidth < 0 ||
136 imageLeft + imageWidth > image.width()) {
137 cerr << "ScrollableImageCache::drawImage: ERROR: Source area (left = "
138 << imageLeft << ", width = " << imageWidth
139 << ") out of bounds for image of "
140 << "width " << image.width() << endl;
141 throw std::logic_error("Source area out of bounds in ScrollableImageCache::drawImage");
142 }
143
144 QPainter painter(&m_image);
145 painter.drawImage(QRect(left, 0, width, m_image.height()),
146 image,
147 QRect(imageLeft, 0, imageWidth, image.height()));
148 painter.end();
149
150 if (!isValid()) {
151 m_left = left;
152 m_width = width;
153 return;
154 }
155
156 if (left < m_left) {
157 if (left + width > m_left + m_width) {
158 // new image completely contains the old valid area --
159 // use the new area as is
160 m_left = left;
161 m_width = width;
162 } else if (left + width < m_left) {
163 // new image completely off left of old valid area --
164 // we can't extend the valid area because the bit in
165 // between is not valid, so must use the new area only
166 m_left = left;
167 m_width = width;
168 } else {
169 // new image overlaps old valid area on left side --
170 // use new left edge, and extend width to existing
171 // right edge
172 m_width = (m_left + m_width) - left;
173 m_left = left;
174 }
175 } else {
176 if (left > m_left + m_width) {
177 // new image completely off right of old valid area --
178 // we can't extend the valid area because the bit in
179 // between is not valid, so must use the new area only
180 m_left = left;
181 m_width = width;
182 } else if (left + width > m_left + m_width) {
183 // new image overlaps old valid area on right side --
184 // use existing left edge, and extend width to new
185 // right edge
186 m_width = (left + width) - m_left;
187 // (m_left unchanged)
188 } else {
189 // new image completely contained within old valid
190 // area -- leave the old area unchanged
191 }
192 }
193 }
194