comparison layer/ScrollableImageCache.cpp @ 1324:13d9b422f7fe zoom

Merge from default branch
author Chris Cannam
date Mon, 17 Sep 2018 13:51:31 +0100
parents a34a2a25907c
children
comparison
equal deleted inserted replaced
1183:57d192e26331 1324:13d9b422f7fe
26 sv_frame_t newStartFrame) 26 sv_frame_t newStartFrame)
27 { 27 {
28 static HitCount count("ScrollableImageCache: scrolling"); 28 static HitCount count("ScrollableImageCache: scrolling");
29 29
30 int dx = (v->getXForFrame(m_startFrame) - 30 int dx = (v->getXForFrame(m_startFrame) -
31 v->getXForFrame(newStartFrame)); 31 v->getXForFrame(newStartFrame));
32 32
33 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE 33 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE
34 cerr << "ScrollableImageCache::scrollTo: start frame " << m_startFrame 34 cerr << "ScrollableImageCache::scrollTo: start frame " << m_startFrame
35 << " -> " << newStartFrame << ", dx = " << dx << endl; 35 << " -> " << newStartFrame << ", dx = " << dx << endl;
36 #endif 36 #endif
37 37
38 if (m_startFrame == newStartFrame) { 38 if (m_startFrame == newStartFrame) {
39 // haven't moved 39 // haven't moved
40 count.hit(); 40 count.hit();
41 return; 41 return;
42 } 42 }
43 43
44 m_startFrame = newStartFrame; 44 m_startFrame = newStartFrame;
45 45
46 if (!isValid()) { 46 if (!isValid()) {
47 count.miss(); 47 count.miss();
48 return; 48 return;
49 } 49 }
50 50
51 int w = m_image.width(); 51 int w = m_image.width();
52 52
53 if (dx == 0) { 53 if (dx == 0) {
54 // haven't moved visibly (even though start frame may have changed) 54 // haven't moved visibly (even though start frame may have changed)
55 count.hit(); 55 count.hit();
56 return; 56 return;
57 } 57 }
58 58
59 if (dx <= -w || dx >= w) { 59 if (dx <= -w || dx >= w) {
60 // scrolled entirely off 60 // scrolled entirely off
61 invalidate(); 61 invalidate();
62 count.miss(); 62 count.miss();
63 return; 63 return;
64 } 64 }
65 65
66 count.partial(); 66 count.partial();
67 67
68 // dx is in range, cache is scrollable 68 // dx is in range, cache is scrollable
69 69
70 int dxp = dx; 70 int dxp = dx;
71 if (dxp < 0) dxp = -dxp; 71 if (dxp < 0) dxp = -dxp;
72 72
73 int copylen = (w - dxp) * int(sizeof(QRgb)); 73 int copylen = (w - dxp) * int(sizeof(QRgb));
74 for (int y = 0; y < m_image.height(); ++y) { 74 for (int y = 0; y < m_image.height(); ++y) {
75 QRgb *line = (QRgb *)m_image.scanLine(y); 75 QRgb *line = (QRgb *)m_image.scanLine(y);
76 if (dx < 0) { 76 if (dx < 0) {
77 memmove(line, line + dxp, copylen); 77 memmove(line, line + dxp, copylen);
78 } else { 78 } else {
79 memmove(line + dxp, line, copylen); 79 memmove(line + dxp, line, copylen);
80 } 80 }
81 } 81 }
82 82
83 // update valid area 83 // update valid area
84 84
85 int px = m_validLeft; 85 int px = m_validLeft;
86 int pw = m_validWidth; 86 int pw = m_validWidth;
87 87
88 px += dx; 88 px += dx;
89 89
90 if (dx < 0) { 90 if (dx < 0) {
91 // we scrolled left 91 // we scrolled left
92 if (px < 0) { 92 if (px < 0) {
93 pw += px; 93 pw += px;
94 px = 0; 94 px = 0;
95 if (pw < 0) { 95 if (pw < 0) {
96 pw = 0; 96 pw = 0;
97 } 97 }
98 } 98 }
99 } else { 99 } else {
100 // we scrolled right 100 // we scrolled right
101 if (px + pw > w) { 101 if (px + pw > w) {
102 pw = w - px; 102 pw = w - px;
103 if (pw < 0) { 103 if (pw < 0) {
104 pw = 0; 104 pw = 0;
105 } 105 }
106 } 106 }
107 } 107 }
108 108
109 m_validLeft = px; 109 m_validLeft = px;
110 m_validWidth = pw; 110 m_validWidth = pw;
111 } 111 }
112 112
113 void 113 void
114 ScrollableImageCache::adjustToTouchValidArea(int &left, int &width, 114 ScrollableImageCache::adjustToTouchValidArea(int &left, int &width,
115 bool &isLeftOfValidArea) const 115 bool &isLeftOfValidArea) const
116 { 116 {
117 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE 117 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE
118 cerr << "ScrollableImageCache::adjustToTouchValidArea: left " << left 118 cerr << "ScrollableImageCache::adjustToTouchValidArea: left " << left
119 << ", width " << width << endl; 119 << ", width " << width << endl;
120 cerr << "ScrollableImageCache: my left " << m_validLeft 120 cerr << "ScrollableImageCache: my left " << m_validLeft
121 << ", width " << m_validWidth << " so right " << (m_validLeft + m_validWidth) << endl; 121 << ", width " << m_validWidth << " so right " << (m_validLeft + m_validWidth) << endl;
122 #endif 122 #endif
123 if (left < m_validLeft) { 123 if (left < m_validLeft) {
124 isLeftOfValidArea = true; 124 isLeftOfValidArea = true;
125 if (left + width <= m_validLeft + m_validWidth) { 125 if (left + width <= m_validLeft + m_validWidth) {
126 width = m_validLeft - left; 126 width = m_validLeft - left;
127 } 127 }
128 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE 128 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE
129 cerr << "ScrollableImageCache: we're left of valid area, adjusted width to " << width << endl; 129 cerr << "ScrollableImageCache: we're left of valid area, adjusted width to " << width << endl;
130 #endif 130 #endif
131 } else { 131 } else {
132 isLeftOfValidArea = false; 132 isLeftOfValidArea = false;
133 width = left + width - (m_validLeft + m_validWidth); 133 width = left + width - (m_validLeft + m_validWidth);
134 left = m_validLeft + m_validWidth; 134 left = m_validLeft + m_validWidth;
135 if (width < 0) width = 0; 135 if (width < 0) width = 0;
136 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE 136 #ifdef DEBUG_SCROLLABLE_IMAGE_CACHE
137 cerr << "ScrollableImageCache: we're right of valid area, adjusted left to " << left << ", width to " << width << endl; 137 cerr << "ScrollableImageCache: we're right of valid area, adjusted left to " << left << ", width to " << width << endl;
138 #endif 138 #endif
139 } 139 }
140 } 140 }
141 141
142 void 142 void
143 ScrollableImageCache::drawImage(int left, 143 ScrollableImageCache::drawImage(int left,
144 int width, 144 int width,
145 QImage image, 145 QImage image,
146 int imageLeft, 146 int imageLeft,
147 int imageWidth) 147 int imageWidth)
148 { 148 {
149 if (image.height() != m_image.height()) { 149 if (image.height() != m_image.height()) {
150 cerr << "ScrollableImageCache::drawImage: ERROR: Supplied image height " 150 cerr << "ScrollableImageCache::drawImage: ERROR: Supplied image height "
151 << image.height() << " does not match cache height " 151 << image.height() << " does not match cache height "
152 << m_image.height() << endl; 152 << m_image.height() << endl;
153 throw std::logic_error("Image height must match cache height in ScrollableImageCache::drawImage"); 153 throw std::logic_error("Image height must match cache height in ScrollableImageCache::drawImage");
154 } 154 }
155 if (left < 0 || width < 0 || left + width > m_image.width()) { 155 if (left < 0 || width < 0 || left + width > m_image.width()) {
156 cerr << "ScrollableImageCache::drawImage: ERROR: Target area (left = " 156 cerr << "ScrollableImageCache::drawImage: ERROR: Target area (left = "
157 << left << ", width = " << width << ", so right = " << left + width 157 << left << ", width = " << width << ", so right = " << left + width
158 << ") out of bounds for cache of width " << m_image.width() << endl; 158 << ") out of bounds for cache of width " << m_image.width() << endl;
159 throw std::logic_error("Target area out of bounds in ScrollableImageCache::drawImage"); 159 throw std::logic_error("Target area out of bounds in ScrollableImageCache::drawImage");
160 } 160 }
161 if (imageLeft < 0 || imageWidth < 0 || 161 if (imageLeft < 0 || imageWidth < 0 ||
162 imageLeft + imageWidth > image.width()) { 162 imageLeft + imageWidth > image.width()) {
163 cerr << "ScrollableImageCache::drawImage: ERROR: Source area (left = " 163 cerr << "ScrollableImageCache::drawImage: ERROR: Source area (left = "
164 << imageLeft << ", width = " << imageWidth << ", so right = " 164 << imageLeft << ", width = " << imageWidth << ", so right = "
165 << imageLeft + imageWidth << ") out of bounds for image of " 165 << imageLeft + imageWidth << ") out of bounds for image of "
166 << "width " << image.width() << endl; 166 << "width " << image.width() << endl;
167 throw std::logic_error("Source area out of bounds in ScrollableImageCache::drawImage"); 167 throw std::logic_error("Source area out of bounds in ScrollableImageCache::drawImage");
168 } 168 }
169 169
170 QPainter painter(&m_image); 170 QPainter painter(&m_image);
171 painter.drawImage(QRect(left, 0, width, m_image.height()), 171 painter.drawImage(QRect(left, 0, width, m_image.height()),
172 image, 172 image,
173 QRect(imageLeft, 0, imageWidth, image.height())); 173 QRect(imageLeft, 0, imageWidth, image.height()));
174 painter.end(); 174 painter.end();
175 175
176 if (!isValid()) { 176 if (!isValid()) {
177 m_validLeft = left; 177 m_validLeft = left;
178 m_validWidth = width; 178 m_validWidth = width;
179 return; 179 return;
180 } 180 }
181 181
182 if (left < m_validLeft) { 182 if (left < m_validLeft) {
183 if (left + width > m_validLeft + m_validWidth) { 183 if (left + width > m_validLeft + m_validWidth) {
184 // new image completely contains the old valid area -- 184 // new image completely contains the old valid area --
185 // use the new area as is 185 // use the new area as is
186 m_validLeft = left; 186 m_validLeft = left;
187 m_validWidth = width; 187 m_validWidth = width;
188 } else if (left + width < m_validLeft) { 188 } else if (left + width < m_validLeft) {
189 // new image completely off left of old valid area -- 189 // new image completely off left of old valid area --
190 // we can't extend the valid area because the bit in 190 // we can't extend the valid area because the bit in
191 // between is not valid, so must use the new area only 191 // between is not valid, so must use the new area only
192 m_validLeft = left; 192 m_validLeft = left;
193 m_validWidth = width; 193 m_validWidth = width;
194 } else { 194 } else {
195 // new image overlaps old valid area on left side -- 195 // new image overlaps old valid area on left side --
196 // use new left edge, and extend width to existing 196 // use new left edge, and extend width to existing
197 // right edge 197 // right edge
198 m_validWidth = (m_validLeft + m_validWidth) - left; 198 m_validWidth = (m_validLeft + m_validWidth) - left;
199 m_validLeft = left; 199 m_validLeft = left;
200 } 200 }
201 } else { 201 } else {
202 if (left > m_validLeft + m_validWidth) { 202 if (left > m_validLeft + m_validWidth) {
203 // new image completely off right of old valid area -- 203 // new image completely off right of old valid area --
204 // we can't extend the valid area because the bit in 204 // we can't extend the valid area because the bit in
205 // between is not valid, so must use the new area only 205 // between is not valid, so must use the new area only
206 m_validLeft = left; 206 m_validLeft = left;
207 m_validWidth = width; 207 m_validWidth = width;
208 } else if (left + width > m_validLeft + m_validWidth) { 208 } else if (left + width > m_validLeft + m_validWidth) {
209 // new image overlaps old valid area on right side -- 209 // new image overlaps old valid area on right side --
210 // use existing left edge, and extend width to new 210 // use existing left edge, and extend width to new
211 // right edge 211 // right edge
212 m_validWidth = (left + width) - m_validLeft; 212 m_validWidth = (left + width) - m_validLeft;
213 // (m_validLeft unchanged) 213 // (m_validLeft unchanged)
214 } else { 214 } else {
215 // new image completely contained within old valid 215 // new image completely contained within old valid
216 // area -- leave the old area unchanged 216 // area -- leave the old area unchanged
217 } 217 }
218 } 218 }
219 } 219 }
220 220