Mercurial > hg > svgui
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 |