Audacity 3.2.0
ImageRoll.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ImageRoll.cpp
6
7 Dominic Mazzoni
8
9*******************************************************************//****************************************************************//*******************************************************************/
96
97
98#include "ImageRoll.h"
99
100#include <wx/bitmap.h>
101#include <wx/dcmemory.h>
102#include <wx/dcclient.h>
103
104ImageRoll::ImageRoll(const ImageRoll&) = default;
105ImageRoll &ImageRoll::operator =(const ImageRoll&) = default;
106ImageRoll::~ImageRoll() = default;
107
108// static
109ImageArray ImageRoll::SplitH(const wxImage &src, wxColour magicColor)
110{
111 ImageArray result;
112
113 int width = src.GetWidth();
114 int height = src.GetHeight();
115 unsigned char *data = src.GetData();
116 unsigned char *ptr = data;
117 unsigned char magicRed = magicColor.Red();
118 unsigned char magicGreen = magicColor.Green();
119 unsigned char magicBlue = magicColor.Blue();
120 bool cur, prev;
121 int i, j, start;
122
123 // Sanity check...
124 if (width<=0 || height<=0 || data==NULL)
125 return result;
126
127 prev = false;
128 start = 0;
129 for(i=0; i<width+1; i++) {
130 if (i < width) {
131 unsigned char *ptr2 = ptr;
132 cur = true;
133 for(j=0; j<height && cur; j++) {
134 if (!(ptr2[0] == magicRed &&
135 ptr2[1] == magicGreen &&
136 ptr2[2] == magicBlue))
137 cur = false;
138 ptr2 += 3 * width;
139 }
140 }
141 else
142 cur = !prev;
143
144 if ((cur && !prev)) {
145 wxRect subRect(start, 0, i-start, height);
146 wxImage subImage;
147 if (subRect.width > 0)
148 subImage = src.GetSubImage(subRect);
149 else
150 subImage = wxImage(subRect.width, subRect.height);
151 result.push_back(subImage);
152 }
153 else if (!cur && prev) {
154 start = i;
155 }
156
157 prev = cur;
158 ptr += 3;
159 }
160
161 return result;
162}
163
164// static
165ImageArray ImageRoll::SplitV(const wxImage &src, wxColour magicColor)
166{
167 ImageArray result;
168 int width = src.GetWidth();
169 int height = src.GetHeight();
170 unsigned char *data = src.GetData();
171 unsigned char *ptr = data;
172 unsigned char magicRed = magicColor.Red();
173 unsigned char magicGreen = magicColor.Green();
174 unsigned char magicBlue = magicColor.Blue();
175 bool cur, prev;
176 int i, j, start;
177
178 // Sanity check...
179 if (width<=0 || height<=0 || data==NULL)
180 return result;
181
182 prev = false;
183 start = 0;
184 for(i=0; i<height+1; i++) {
185 if (i < height) {
186 unsigned char *ptr2 = ptr;
187 cur = true;
188 for(j=0; j<width && cur; j++) {
189 if (!(ptr2[0] == magicRed &&
190 ptr2[1] == magicGreen &&
191 ptr2[2] == magicBlue))
192 cur = false;
193 ptr2 += 3;
194 }
195 }
196 else
197 cur = !prev;
198
199 if ((cur && !prev)) {
200 wxRect subRect(0, start, width, i-start);
201 wxImage subImage;
202 if (subRect.width > 0)
203 subImage = src.GetSubImage(subRect);
204 else
205 subImage = wxImage(subRect.width, subRect.height);
206 result.push_back(subImage);
207 }
208 else if (!cur && prev) {
209 start = i;
210 }
211
212 prev = cur;
213 ptr += 3*width;
214 }
215
216 return result;
217}
218
219void ImageRoll::Init(RollType type, const wxImage &src, wxColour magicColor)
220{
221 ImageArray images;
222 int i;
223
224 mType = type;
225
226 switch(mType) {
227 case HorizontalRoll:
228 images = SplitH(src, magicColor);
229
230 mMinSize.x = 0;
231 mMinSize.y = src.GetHeight();
232 mMaxSize.x = 9999;
233 mMaxSize.y = src.GetHeight();
234
235 for(i = 0; i < (int)images.size(); i++) {
236 if (images[i].Ok()) {
237 mPieces.push_back(wxBitmap(images[i]));
238 mMinSize.x += mPieces[i].GetWidth();
239 }
240 else
241 mPieces.push_back(wxBitmap());
242 }
243 break;
244
245 case VerticalRoll:
246 images = SplitV(src, magicColor);
247
248 mMinSize.x = src.GetWidth();
249 mMinSize.y = 0;
250 mMaxSize.x = src.GetWidth();
251 mMaxSize.y = 9999;
252
253 for(i = 0; i < (int)images.size(); i++) {
254 if (images[i].Ok()) {
255 mPieces.push_back(wxBitmap(images[i]));
256 mMinSize.y += mPieces[i].GetHeight();
257 }
258 else
259 mPieces.push_back(wxBitmap());
260 }
261 break;
262
263 case FixedImage:
264 mPieces.push_back(wxBitmap(src));
265 mMinSize.x = src.GetWidth();
266 mMinSize.y = src.GetHeight();
267 mMaxSize.x = src.GetWidth();
268 mMaxSize.y = src.GetHeight();
269 break;
270
271 /* Adding these shuts up some GCC warnings. It is functionally what was
272 * implicit here before - Richard */
273 case Uninitialized:
274 break;
275
276 case Frame:
277 break;
278
279 } // switch
280}
281
283{
285}
286
287ImageRoll::ImageRoll(RollType type, const wxImage &src, wxColour magicColor)
288{
289 Init(type, src, magicColor);
290}
291
293{
294 Init(FixedImage, src, *wxWHITE);
295}
296
297bool ImageRoll::Ok() const
298{
299 return (mType != Uninitialized);
300}
301
302void ImageRoll::DrawBitmap(wxDC &dc, wxBitmap &bitmap,
303 int x, int y, int logicalFunc)
304{
305 auto func = static_cast< wxRasterOperationMode >( logicalFunc );
306 if (func == wxCOPY)
307 dc.DrawBitmap(bitmap, x, y);
308 else {
309 wxMemoryDC memDC;
310 memDC.SelectObject(bitmap);
311 dc.Blit(x, y, bitmap.GetWidth(), bitmap.GetHeight(),
312 &memDC, 0, 0, func);
313 }
314}
315
316void ImageRoll::Draw(wxDC &dc, wxRect rect)
317{
318 Draw( dc, rect, wxCOPY );
319}
320
321void ImageRoll::Draw(wxDC &dc, wxRect rect, int WXUNUSED(logicalFunc))
322{
323 auto func = wxCOPY;
324 int width = rect.width;
325 int height = rect.height;
326 int num = (int)mPieces.size();
327 int i, j;
328
329 switch(mType) {
330 case HorizontalRoll: {
331 // The pieces alternate fixed, rolling, fixed, rolling...
332
333 int fixedWidth = 0;
334 for(i=0; i<num; i+=2)
335 fixedWidth += (mPieces[i].Ok() ? mPieces[i].GetWidth() : 0);
336
337 int rollingSpace = width - fixedWidth;
338 int numRolling = num / 2;
339 int x = 0;
340
341 for(i=0; i<num; i++) {
342 int w = (mPieces[i].Ok() ? mPieces[i].GetWidth() : 0);
343
344 if (i%2==0) {
345 // fixed
346
347 if (mPieces[i].Ok())
348 DrawBitmap(dc, mPieces[i], rect.x + x, rect.y, func);
349 x += w;
350 }
351 else {
352 // rolling
353
354 int space =
355 ((1+(i/2))*rollingSpace / numRolling) -
356 ((i/2)*rollingSpace / numRolling);
357
358 j = 0;
359 while(j < space) {
360 if (mPieces[i].Ok())
361 DrawBitmap(dc, mPieces[i], rect.x + x + j, rect.y, func);
362 j += w;
363 }
364
365 x += space;
366 }
367 }
368 } break; // case HorizontalRoll
369
370 case VerticalRoll: {
371 // The pieces alternate fixed, rolling, fixed, rolling...
372
373 int fixedHeight = 0;
374 for(i=0; i<num; i+=2)
375 fixedHeight += (mPieces[i].Ok() ? mPieces[i].GetHeight() : 0);
376
377 int rollingSpace = height - fixedHeight;
378 int numRolling = num / 2;
379 int y = 0;
380
381 for(i=0; i<num; i++) {
382 int h = (mPieces[i].Ok() ? mPieces[i].GetHeight() : 0);
383
384 if (i%2==0) {
385 // fixed
386
387 if (mPieces[i].Ok())
388 DrawBitmap(dc, mPieces[i], rect.x, rect.y + y, func);
389 y += h;
390 }
391 else {
392 // rolling
393
394 int space =
395 ((1+(i/2))*rollingSpace / numRolling) -
396 ((i/2)*rollingSpace / numRolling);
397
398 j = 0;
399 while(j < space) {
400 if (mPieces[i].Ok())
401 DrawBitmap(dc, mPieces[i], rect.x, rect.y + y + j, func);
402 j += h;
403 }
404
405 y += space;
406 }
407 }
408 } break; // case VerticalRoll
409
410 case FixedImage:
411 DrawBitmap(dc, mPieces[0], rect.x, rect.y, func);
412 break;
413 /* the other possible cases don't really make sense, but not having them
414 * listed gives a GCC warning */
415 case Uninitialized:
416 break;
417
418 case Frame:
419 break;
420
421 } // switch
422}
wxImage(22, 22)
#define wxRasterOperationMode
Definition: ImageRoll.h:21
std::vector< wxImage > ImageArray
Definition: ImageRoll.h:25
An ImageRoll is an image that can be expanded to an arbitrary size; it is made up of both fixed piece...
Definition: ImageRoll.h:28
void Draw(wxDC &dc, wxRect rect, int logicalFunc)
void Init(RollType type, const wxImage &src, wxColour magicColor)
Definition: ImageRoll.cpp:219
wxSize mMinSize
Definition: ImageRoll.h:68
bool Ok() const
Definition: ImageRoll.cpp:297
static ImageArray SplitV(const wxImage &src, wxColour magicColor)
Definition: ImageRoll.cpp:165
ImageRoll & operator=(const ImageRoll &)
@ FixedImage
Definition: ImageRoll.h:32
@ VerticalRoll
Definition: ImageRoll.h:34
@ HorizontalRoll
Definition: ImageRoll.h:33
@ Uninitialized
Definition: ImageRoll.h:31
void DrawBitmap(wxDC &dc, wxBitmap &bitmap, int x, int y, int logicalFunc)
Definition: ImageRoll.cpp:302
std::vector< wxBitmap > mPieces
Definition: ImageRoll.h:67
wxSize mMaxSize
Definition: ImageRoll.h:69
static ImageArray SplitH(const wxImage &src, wxColour magicColor)
Definition: ImageRoll.cpp:109
RollType mType
Definition: ImageRoll.h:65