]> git.saurik.com Git - wxWidgets.git/blob - src/mac/bitmap.cpp
oops, typo leading to compilation problem fixed
[wxWidgets.git] / src / mac / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: bitmap.cpp
3 // Purpose: wxBitmap
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "bitmap.h"
14 #endif
15
16 #include "wx/wx.h"
17 #include "wx/setup.h"
18 #include "wx/utils.h"
19 #include "wx/palette.h"
20 #include "wx/bitmap.h"
21 #include "wx/icon.h"
22 #include "wx/log.h"
23 #include "wx/image.h"
24 #include "wx/xpmdecod.h"
25
26 extern "C"
27 {
28 #ifdef OBSOLETE_XPM_DATA_HANDLER
29 #include "xpm.h"
30 #endif
31 } ;
32
33 #if !USE_SHARED_LIBRARIES
34 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
35 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
36 #endif
37
38 #ifdef __UNIX__
39 #include <ApplicationServices/ApplicationServices.h>
40 #else
41 #include <PictUtils.h>
42 #endif
43
44 #include "wx/mac/uma.h"
45
46 CTabHandle wxMacCreateColorTable( int numColors )
47 {
48 CTabHandle newColors; /* Handle to the new color table */
49
50 /* Allocate memory for the color table */
51 newColors = (CTabHandle)NewHandleClear( sizeof (ColorTable) +
52 sizeof (ColorSpec) * (numColors - 1) );
53 if (newColors != nil)
54 {
55 /* Initialize the fields */
56 (**newColors).ctSeed = GetCTSeed();
57 (**newColors).ctFlags = 0;
58 (**newColors).ctSize = numColors - 1;
59 /* Initialize the table of colors */
60 }
61 return newColors ;
62 }
63
64 void wxMacDestroyColorTable( CTabHandle colors )
65 {
66 DisposeHandle( (Handle) colors ) ;
67 }
68
69 void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue )
70 {
71 (**newColors).ctTable[index].value = index;
72 (**newColors).ctTable[index].rgb.red = 0 ;// someRedValue;
73 (**newColors).ctTable[index].rgb.green = 0 ; // someGreenValue;
74 (**newColors).ctTable[index].rgb.blue = 0 ; // someBlueValue;
75 }
76
77 GWorldPtr wxMacCreateGWorld( int width , int height , int depth )
78 {
79 OSErr err = noErr ;
80 GWorldPtr port ;
81 Rect rect = { 0 , 0 , height , width } ;
82
83 if ( depth < 0 )
84 {
85 depth = wxDisplayDepth() ;
86 }
87
88 err = NewGWorld( &port , depth , &rect , NULL , NULL , 0 ) ;
89 if ( err == noErr )
90 {
91 return port ;
92 }
93 return NULL ;
94 }
95
96 void wxMacDestroyGWorld( GWorldPtr gw )
97 {
98 if ( gw )
99 DisposeGWorld( gw ) ;
100 }
101
102 PicHandle wxMacCreatePict(GWorldPtr wp, GWorldPtr mask)
103 {
104 CGrafPtr origPort ;
105 GDHandle origDev ;
106
107 PicHandle pict; // this is the Picture we give back
108
109 RGBColor gray = { 0xCCCC ,0xCCCC , 0xCCCC } ;
110 RGBColor white = { 0xffff ,0xffff , 0xffff } ;
111 RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ;
112
113 unsigned char *maskimage = NULL ;
114 Rect portRect ;
115 GetPortBounds( wp , &portRect ) ;
116 int width = portRect.right - portRect.left ;
117 int height = portRect.bottom - portRect.top ;
118
119 LockPixels( GetGWorldPixMap( wp ) ) ;
120 GetGWorld( &origPort , &origDev ) ;
121
122 if ( mask )
123 {
124 maskimage = (unsigned char*) malloc( width * height ) ;
125 SetGWorld( mask , NULL ) ;
126 LockPixels( GetGWorldPixMap( mask ) ) ;
127 for ( int y = 0 ; y < height ; y++ )
128 {
129 for( int x = 0 ; x < width ; x++ )
130 {
131 RGBColor col ;
132
133 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
134 maskimage[y*width + x] = ( col.red == 0 ) ; // for monochrome masks
135 }
136 }
137 UnlockPixels( GetGWorldPixMap( mask ) ) ;
138 }
139
140 SetGWorld( wp , NULL ) ;
141
142 pict = OpenPicture(&portRect); // open a picture, this disables drawing
143 if(!pict)
144 return NULL;
145
146 if ( maskimage )
147 {
148 RGBForeColor( &black ) ;
149 RGBBackColor( &white ) ;
150 PenMode(transparent);
151
152 for ( int y = 0 ; y < height ; ++y )
153 {
154 for( int x = 0 ; x < width ; ++x )
155 {
156 if ( maskimage[y*width + x] )
157 {
158 RGBColor col ;
159
160 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
161 SetCPixel( x + portRect.left , y + portRect.top , &col ) ;
162 }
163 else {
164 // With transparency set this sets a blank pixel not a white one
165 SetCPixel( x + portRect.left , y + portRect.top , &white);
166 }
167 }
168 }
169 free( maskimage ) ;
170 maskimage = NULL ;
171 }
172 else
173 {
174 RGBBackColor( &gray ) ;
175 EraseRect(&portRect);
176 RGBForeColor( &black ) ;
177 RGBBackColor( &white ) ;
178
179 CopyBits(GetPortBitMapForCopyBits(wp), /* src PixMap - we copy image over
180 * itself - */
181 GetPortBitMapForCopyBits(wp), // dst PixMap - no drawing occurs
182 &portRect, // srcRect - it will be recorded and compressed -
183 &portRect, // dstRect - into the picture that is open -
184 srcCopy,NULL); // copyMode and no clip region
185 }
186 ClosePicture(); // We are done recording the picture
187 UnlockPixels( GetGWorldPixMap( wp ) ) ;
188 SetGWorld( origPort , origDev ) ;
189
190 return pict; // return our groovy pict handle
191 }
192
193 wxBitmapRefData::wxBitmapRefData()
194 {
195 m_ok = FALSE;
196 m_width = 0;
197 m_height = 0;
198 m_depth = 0;
199 m_quality = 0;
200 m_numColors = 0;
201 m_bitmapMask = NULL;
202 m_hBitmap = NULL ;
203 m_hPict = NULL ;
204 m_hIcon = NULL ;
205 m_bitmapType = kMacBitmapTypeUnknownType ;
206 }
207
208 wxBitmapRefData::~wxBitmapRefData()
209 {
210 switch (m_bitmapType)
211 {
212 case kMacBitmapTypePict :
213 {
214 if ( m_hPict )
215 {
216 KillPicture( m_hPict ) ;
217 m_hPict = NULL ;
218 }
219 }
220 break ;
221 case kMacBitmapTypeGrafWorld :
222 {
223 if ( m_hBitmap )
224 {
225 wxMacDestroyGWorld( m_hBitmap ) ;
226 m_hBitmap = NULL ;
227 }
228 }
229 break ;
230 case kMacBitmapTypeIcon :
231 if ( m_hIcon )
232 {
233 DisposeCIcon( m_hIcon ) ;
234 m_hIcon = NULL ;
235 }
236
237 default :
238 // unkown type ?
239 break ;
240 }
241
242 if (m_bitmapMask)
243 {
244 delete m_bitmapMask;
245 m_bitmapMask = NULL;
246 }
247 }
248
249 wxList wxBitmap::sm_handlers;
250
251 wxBitmap::wxBitmap()
252 {
253 m_refData = NULL;
254
255 if ( wxTheBitmapList )
256 wxTheBitmapList->AddBitmap(this);
257 }
258
259 wxBitmap::~wxBitmap()
260 {
261 if (wxTheBitmapList)
262 wxTheBitmapList->DeleteObject(this);
263 }
264
265 wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
266 {
267 m_refData = new wxBitmapRefData;
268
269 M_BITMAPDATA->m_width = the_width ;
270 M_BITMAPDATA->m_height = the_height ;
271 M_BITMAPDATA->m_depth = no_bits ;
272 M_BITMAPDATA->m_numColors = 0;
273 if ( no_bits == 1 )
274 {
275 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
276 M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( the_width , the_height , no_bits ) ;
277 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
278
279 CGrafPtr origPort ;
280 GDHandle origDevice ;
281
282 GetGWorld( &origPort , &origDevice ) ;
283 SetGWorld( M_BITMAPDATA->m_hBitmap , NULL ) ;
284 LockPixels( GetGWorldPixMap( M_BITMAPDATA->m_hBitmap ) ) ;
285
286 // bits is a char array
287
288 unsigned char* linestart = (unsigned char*) bits ;
289 int linesize = ( the_width / (sizeof(unsigned char) * 8)) ;
290 if ( the_width % (sizeof(unsigned char) * 8) ) {
291 linesize += sizeof(unsigned char);
292 }
293
294 RGBColor colors[2] = {
295 { 0xFFFF , 0xFFFF , 0xFFFF } ,
296 { 0, 0 , 0 }
297 } ;
298
299 for ( int y = 0 ; y < the_height ; ++y , linestart += linesize )
300 {
301 for ( int x = 0 ; x < the_width ; ++x )
302 {
303 int index = x / 8 ;
304 int bit = x % 8 ;
305 int mask = 1 << bit ;
306 if ( linestart[index] & mask )
307 {
308 SetCPixel( x , y , &colors[1] ) ;
309 }
310 else
311 {
312 SetCPixel( x , y , &colors[0] ) ;
313 }
314 }
315 }
316 UnlockPixels( GetGWorldPixMap( M_BITMAPDATA->m_hBitmap ) ) ;
317
318 SetGWorld( origPort , origDevice ) ;
319 }
320 else
321 {
322 wxFAIL_MSG(wxT("multicolor BITMAPs not yet implemented"));
323 }
324
325 if ( wxTheBitmapList ) {
326 wxTheBitmapList->AddBitmap(this);
327 }
328 }
329
330 wxBitmap::wxBitmap(int w, int h, int d)
331 {
332 (void)Create(w, h, d);
333
334 if ( wxTheBitmapList )
335 wxTheBitmapList->AddBitmap(this);
336 }
337
338 wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
339 {
340 (void) Create(data, type, width, height, depth);
341
342 if ( wxTheBitmapList )
343 wxTheBitmapList->AddBitmap(this);
344 }
345
346 wxBitmap::wxBitmap(const wxString& filename, long type)
347 {
348 LoadFile(filename, (int)type);
349
350 if ( wxTheBitmapList )
351 wxTheBitmapList->AddBitmap(this);
352 }
353
354 bool wxBitmap::CreateFromXpm(const char **bits)
355 {
356 wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") )
357 wxXPMDecoder decoder;
358 wxImage img = decoder.ReadData(bits);
359 wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid bitmap data") )
360 *this = wxBitmap(img);
361 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
362 return TRUE;
363 }
364
365 wxBitmap::wxBitmap(const char **bits)
366 {
367 #ifdef OBSOLETE_XPM_DATA_HANDLER
368 (void) Create((void *)bits, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
369 #else
370 (void) CreateFromXpm(bits);
371 #endif
372 }
373
374 wxBitmap::wxBitmap(char **bits)
375 {
376 #ifdef OBSOLETE_XPM_DATA_HANDLER
377 (void) Create((void *)bits, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
378 #else
379 (void) CreateFromXpm((const char **)bits);
380 #endif
381 }
382
383 wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const
384 {
385 wxCHECK_MSG( Ok() &&
386 (rect.x >= 0) && (rect.y >= 0) &&
387 (rect.x+rect.width <= GetWidth()) &&
388 (rect.y+rect.height <= GetHeight()),
389 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
390
391
392 wxBitmap ret( rect.width, rect.height, GetDepth() );
393 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
394
395 WXHBITMAP origPort;
396 GDHandle origDevice;
397
398 GetGWorld( &origPort, &origDevice );
399
400 // Update the subbitmaps reference data
401 wxBitmapRefData *ref = (wxBitmapRefData *)ret.GetRefData();
402
403 ref->m_numColors = M_BITMAPDATA->m_numColors;
404 ref->m_bitmapPalette = M_BITMAPDATA->m_bitmapPalette;
405 ref->m_bitmapType = M_BITMAPDATA->m_bitmapType;
406
407 // Copy sub region of this bitmap
408 if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypePict)
409 {
410 printf("GetSubBitmap: Copy a region of a Pict structure - TODO\n");
411 }
412 else if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypeGrafWorld)
413 {
414 // Copy mask
415 if(GetMask())
416 {
417 WXHBITMAP submask, mask;
418 RGBColor color;
419
420 mask = GetMask()->GetMaskBitmap();
421 submask = wxMacCreateGWorld(rect.width, rect.height, 1);
422 LockPixels(GetGWorldPixMap(mask));
423 LockPixels(GetGWorldPixMap(submask));
424
425 for(int yy = 0; yy < rect.height; yy++)
426 {
427 for(int xx = 0; xx < rect.width; xx++)
428 {
429 SetGWorld(mask, NULL);
430 GetCPixel(rect.x + xx, rect.y + yy, &color);
431 SetGWorld(submask, NULL);
432 SetCPixel(xx,yy, &color);
433 }
434 }
435 UnlockPixels(GetGWorldPixMap(mask));
436 UnlockPixels(GetGWorldPixMap(submask));
437 ref->m_bitmapMask = new wxMask;
438 ref->m_bitmapMask->SetMaskBitmap(submask);
439 }
440
441 // Copy bitmap
442 if(GetHBITMAP())
443 {
444 WXHBITMAP subbitmap, bitmap;
445 RGBColor color;
446
447 bitmap = GetHBITMAP();
448 subbitmap = wxMacCreateGWorld(rect.width, rect.height, GetDepth());
449 LockPixels(GetGWorldPixMap(bitmap));
450 LockPixels(GetGWorldPixMap(subbitmap));
451
452 for(int yy = 0; yy < rect.height; yy++)
453 {
454 for(int xx = 0; xx < rect.width; xx++)
455 {
456 SetGWorld(bitmap, NULL);
457 GetCPixel(rect.x + xx, rect.y + yy, &color);
458 SetGWorld(subbitmap, NULL);
459 SetCPixel(xx, yy, &color);
460 }
461 }
462 UnlockPixels(GetGWorldPixMap(bitmap));
463 UnlockPixels(GetGWorldPixMap(subbitmap));
464 ret.SetHBITMAP(subbitmap);
465 }
466 }
467 SetGWorld( origPort, origDevice );
468
469 return ret;
470 }
471
472 bool wxBitmap::Create(int w, int h, int d)
473 {
474 UnRef();
475
476 m_refData = new wxBitmapRefData;
477
478 M_BITMAPDATA->m_width = w;
479 M_BITMAPDATA->m_height = h;
480 M_BITMAPDATA->m_depth = d;
481
482 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
483 M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( w , h , d ) ;
484 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
485 return M_BITMAPDATA->m_ok;
486 }
487
488 int wxBitmap::GetBitmapType() const
489 {
490 wxCHECK_MSG( Ok(), kMacBitmapTypeUnknownType, wxT("invalid bitmap") );
491
492 return M_BITMAPDATA->m_bitmapType;
493 }
494
495 void wxBitmap::SetHBITMAP(WXHBITMAP bmp)
496 {
497 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
498 M_BITMAPDATA->m_hBitmap = bmp ;
499 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
500 }
501
502 bool wxBitmap::LoadFile(const wxString& filename, long type)
503 {
504 UnRef();
505
506 m_refData = new wxBitmapRefData;
507
508 wxBitmapHandler *handler = FindHandler(type);
509
510 if ( handler == NULL ) {
511 wxLogWarning("no bitmap handler for type %d defined.", type);
512
513 return FALSE;
514 }
515
516 return handler->LoadFile(this, filename, type, -1, -1);
517 }
518
519 bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
520 {
521 UnRef();
522
523 m_refData = new wxBitmapRefData;
524
525 wxBitmapHandler *handler = FindHandler(type);
526
527 if ( handler == NULL ) {
528 wxLogWarning("no bitmap handler for type %d defined.", type);
529
530 return FALSE;
531 }
532
533 return handler->Create(this, data, type, width, height, depth);
534 }
535
536 wxBitmap::wxBitmap(const wxImage& image, int depth)
537 {
538 wxCHECK_RET( image.Ok(), wxT("invalid image") )
539 wxCHECK_RET( depth == -1, wxT("invalid bitmap depth") )
540
541 m_refData = new wxBitmapRefData();
542
543 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
544
545 // width and height of the device-dependent bitmap
546 int width = image.GetWidth();
547 int height = image.GetHeight();
548
549 // Create picture
550
551 Create( width , height , wxDisplayDepth() ) ;
552 wxBitmap maskBitmap( width, height, 1);
553
554 CGrafPtr origPort ;
555 GDHandle origDevice ;
556
557 LockPixels( GetGWorldPixMap(GetHBITMAP()) );
558 LockPixels( GetGWorldPixMap(maskBitmap.GetHBITMAP()) );
559
560 GetGWorld( &origPort , &origDevice ) ;
561 SetGWorld( GetHBITMAP() , NULL ) ;
562
563 // Render image
564 wxColour rgb, maskcolor(image.GetMaskRed(), image.GetMaskGreen(), image.GetMaskBlue());
565 RGBColor color;
566 RGBColor white = { 0xffff, 0xffff, 0xffff };
567 RGBColor black = { 0 , 0 , 0 };
568
569 register unsigned char* data = image.GetData();
570
571 int index = 0;
572 for (int y = 0; y < height; y++)
573 {
574 for (int x = 0; x < width; x++)
575 {
576 rgb.Set(data[index++], data[index++], data[index++]);
577 color = rgb.GetPixel();
578 SetCPixel( x , y , &color ) ;
579 if (image.HasMask())
580 {
581 SetGWorld(maskBitmap.GetHBITMAP(), NULL);
582 if (rgb == maskcolor) {
583 SetCPixel(x,y, &white);
584 }
585 else {
586 SetCPixel(x,y, &black);
587 }
588 SetGWorld(GetHBITMAP(), NULL);
589 }
590 }
591 } // for height
592
593 // Create mask
594 if ( image.HasMask() ) {
595 SetMask(new wxMask( maskBitmap ));
596 }
597
598 UnlockPixels( GetGWorldPixMap(GetHBITMAP()) );
599 UnlockPixels( GetGWorldPixMap(maskBitmap.GetHBITMAP()) );
600 SetGWorld( origPort, origDevice );
601 }
602
603 wxImage wxBitmap::ConvertToImage() const
604 {
605 wxImage image;
606
607 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
608
609 // create an wxImage object
610 int width = GetWidth();
611 int height = GetHeight();
612 image.Create( width, height );
613
614 unsigned char *data = image.GetData();
615
616 wxCHECK_MSG( data, wxNullImage, wxT("Could not allocate data for image") );
617
618 WXHBITMAP origPort;
619 GDHandle origDevice;
620 int index;
621 RGBColor color;
622 // background color set to RGB(16,16,16) in consistent with wxGTK
623 unsigned char mask_r=16, mask_g=16, mask_b=16;
624 SInt16 r,g,b;
625 wxMask *mask = GetMask();
626
627 GetGWorld( &origPort, &origDevice );
628 LockPixels(GetGWorldPixMap(GetHBITMAP()));
629 SetGWorld( GetHBITMAP(), NULL);
630
631 // Copy data into image
632 index = 0;
633 for (int yy = 0; yy < height; yy++)
634 {
635 for (int xx = 0; xx < width; xx++)
636 {
637 GetCPixel(xx,yy, &color);
638 r = ((color.red ) >> 8);
639 g = ((color.green ) >> 8);
640 b = ((color.blue ) >> 8);
641 data[index ] = r;
642 data[index + 1] = g;
643 data[index + 2] = b;
644 if (mask)
645 {
646 if (mask->PointMasked(xx,yy))
647 {
648 data[index ] = mask_r;
649 data[index + 1] = mask_g;
650 data[index + 2] = mask_b;
651 }
652 }
653 index += 3;
654 }
655 }
656 if (mask)
657 {
658 image.SetMaskColour( mask_r, mask_g, mask_b );
659 image.SetMask( true );
660 }
661
662 // Free resources
663 UnlockPixels(GetGWorldPixMap(GetHBITMAP()));
664 SetGWorld(origPort, origDevice);
665
666 return image;
667 }
668
669
670 bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
671 {
672 wxBitmapHandler *handler = FindHandler(type);
673
674 if ( handler == NULL ) {
675 wxLogWarning("no bitmap handler for type %d defined.", type);
676
677 return FALSE;
678 }
679
680 return handler->SaveFile(this, filename, type, palette);
681 }
682
683 bool wxBitmap::Ok() const
684 {
685 return (M_BITMAPDATA && M_BITMAPDATA->m_ok);
686 }
687
688 int wxBitmap::GetHeight() const
689 {
690 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
691
692 return M_BITMAPDATA->m_height;
693 }
694
695 int wxBitmap::GetWidth() const
696 {
697 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
698
699 return M_BITMAPDATA->m_width;
700 }
701
702 int wxBitmap::GetDepth() const
703 {
704 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
705
706 return M_BITMAPDATA->m_depth;
707 }
708
709 int wxBitmap::GetQuality() const
710 {
711 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
712
713 return M_BITMAPDATA->m_quality;
714 }
715
716 wxMask *wxBitmap::GetMask() const
717 {
718 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
719
720 return M_BITMAPDATA->m_bitmapMask;
721 }
722
723 void wxBitmap::SetWidth(int w)
724 {
725 if (!M_BITMAPDATA)
726 m_refData = new wxBitmapRefData;
727
728 M_BITMAPDATA->m_width = w;
729 }
730
731 void wxBitmap::SetHeight(int h)
732 {
733 if (!M_BITMAPDATA)
734 m_refData = new wxBitmapRefData;
735
736 M_BITMAPDATA->m_height = h;
737 }
738
739 void wxBitmap::SetDepth(int d)
740 {
741 if (!M_BITMAPDATA)
742 m_refData = new wxBitmapRefData;
743
744 M_BITMAPDATA->m_depth = d;
745 }
746
747 void wxBitmap::SetQuality(int q)
748 {
749 if (!M_BITMAPDATA)
750 m_refData = new wxBitmapRefData;
751
752 M_BITMAPDATA->m_quality = q;
753 }
754
755 void wxBitmap::SetOk(bool isOk)
756 {
757 if (!M_BITMAPDATA)
758 m_refData = new wxBitmapRefData;
759
760 M_BITMAPDATA->m_ok = isOk;
761 }
762
763 wxPalette *wxBitmap::GetPalette() const
764 {
765 wxCHECK_MSG( Ok(), NULL, wxT("Invalid bitmap GetPalette()") );
766
767 return &M_BITMAPDATA->m_bitmapPalette;
768 }
769
770 void wxBitmap::SetPalette(const wxPalette& palette)
771 {
772 if (!M_BITMAPDATA)
773 m_refData = new wxBitmapRefData;
774
775 M_BITMAPDATA->m_bitmapPalette = palette ;
776 }
777
778 void wxBitmap::SetMask(wxMask *mask)
779 {
780 if (!M_BITMAPDATA)
781 m_refData = new wxBitmapRefData;
782
783 M_BITMAPDATA->m_bitmapMask = mask ;
784 }
785
786 WXHBITMAP wxBitmap::GetHBITMAP() const
787 {
788 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
789
790 return M_BITMAPDATA->m_hBitmap;
791 }
792
793 PicHandle wxBitmap::GetPict() const
794 {
795 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
796
797 PicHandle picture; // This is the returned picture
798
799 // If bitmap already in Pict format return pointer
800 if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypePict) {
801 return M_BITMAPDATA->m_hPict;
802 }
803 else if(M_BITMAPDATA->m_bitmapType != kMacBitmapTypeGrafWorld) {
804 // Invalid bitmap
805 return NULL;
806 }
807
808 RGBColor gray = { 0xCCCC ,0xCCCC , 0xCCCC } ;
809 RGBColor white = { 0xffff ,0xffff , 0xffff } ;
810 RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ;
811 CGrafPtr origPort;
812 GDHandle origDev ;
813 wxMask *mask;
814 Rect portRect ;
815
816 GetPortBounds( GetHBITMAP() , &portRect ) ;
817 int width = portRect.right - portRect.left ;
818 int height = portRect.bottom - portRect.top ;
819
820 LockPixels( GetGWorldPixMap( GetHBITMAP() ) ) ;
821 GetGWorld( &origPort , &origDev ) ;
822
823 mask = GetMask();
824
825 SetGWorld( GetHBITMAP() , NULL ) ;
826
827 picture = OpenPicture(&portRect); // open a picture, this disables drawing
828 if(!picture) {
829 return NULL;
830 }
831
832 if( mask )
833 {
834 #ifdef __UNIX__
835 RGBColor trans = white;
836 #else
837 RGBBackColor( &gray );
838 EraseRect( &portRect );
839 RGBColor trans = gray;
840 #endif
841 RGBForeColor( &black ) ;
842 RGBBackColor( &white ) ;
843 PenMode(transparent);
844
845 for ( int y = 0 ; y < height ; ++y )
846 {
847 for( int x = 0 ; x < width ; ++x )
848 {
849 if ( !mask->PointMasked(x,y) )
850 {
851 RGBColor col ;
852
853 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
854 SetCPixel( x + portRect.left , y + portRect.top , &col ) ;
855 }
856 else {
857 // With transparency this sets a blank pixel
858 SetCPixel( x + portRect.left , y + portRect.top , &trans);
859 }
860 }
861 }
862 }
863 else
864 {
865 RGBBackColor( &gray ) ;
866 EraseRect(&portRect);
867 RGBForeColor( &black ) ;
868 RGBBackColor( &white ) ;
869
870 CopyBits(GetPortBitMapForCopyBits(GetHBITMAP()),
871 // src PixMap - we copy image over itself -
872 GetPortBitMapForCopyBits(GetHBITMAP()),
873 // dst PixMap - no drawing occurs
874 &portRect, // srcRect - it will be recorded and compressed -
875 &portRect, // dstRect - into the picture that is open -
876 srcCopy,NULL); // copyMode and no clip region
877 }
878 ClosePicture(); // We are done recording the picture
879 UnlockPixels( GetGWorldPixMap( GetHBITMAP() ) ) ;
880 SetGWorld( origPort , origDev ) ;
881
882 return picture; // return our groovy pict handle
883 }
884
885 void wxBitmap::AddHandler(wxBitmapHandler *handler)
886 {
887 sm_handlers.Append(handler);
888 }
889
890 void wxBitmap::InsertHandler(wxBitmapHandler *handler)
891 {
892 sm_handlers.Insert(handler);
893 }
894
895 bool wxBitmap::RemoveHandler(const wxString& name)
896 {
897 wxBitmapHandler *handler = FindHandler(name);
898 if ( handler )
899 {
900 sm_handlers.DeleteObject(handler);
901 return TRUE;
902 }
903 else
904 return FALSE;
905 }
906
907 wxBitmapHandler *wxBitmap::FindHandler(const wxString& name)
908 {
909 wxNode *node = sm_handlers.First();
910 while ( node )
911 {
912 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
913 if ( handler->GetName() == name )
914 return handler;
915 node = node->Next();
916 }
917 return NULL;
918 }
919
920 wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, long bitmapType)
921 {
922 wxNode *node = sm_handlers.First();
923 while ( node )
924 {
925 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
926 if ( handler->GetExtension() == extension &&
927 (bitmapType == -1 || handler->GetType() == bitmapType) )
928 return handler;
929 node = node->Next();
930 }
931 return NULL;
932 }
933
934 wxBitmapHandler *wxBitmap::FindHandler(long bitmapType)
935 {
936 wxNode *node = sm_handlers.First();
937 while ( node )
938 {
939 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
940 if (handler->GetType() == bitmapType)
941 return handler;
942 node = node->Next();
943 }
944 return NULL;
945 }
946
947 /*
948 * wxMask
949 */
950
951 wxMask::wxMask()
952 {
953 m_maskBitmap = 0;
954 }
955
956 // Construct a mask from a bitmap and a colour indicating
957 // the transparent area
958 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
959 {
960 m_maskBitmap = 0;
961 Create(bitmap, colour);
962 }
963
964 // Construct a mask from a bitmap and a palette index indicating
965 // the transparent area
966 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
967 {
968 m_maskBitmap = 0;
969 Create(bitmap, paletteIndex);
970 }
971
972 // Construct a mask from a mono bitmap (copies the bitmap).
973 wxMask::wxMask(const wxBitmap& bitmap)
974 {
975 m_maskBitmap = 0;
976 Create(bitmap);
977 }
978
979 wxMask::~wxMask()
980 {
981 if ( m_maskBitmap )
982 {
983 wxMacDestroyGWorld( m_maskBitmap ) ;
984 m_maskBitmap = NULL ;
985 }
986 }
987
988 // Create a mask from a mono bitmap (copies the bitmap).
989 bool wxMask::Create(const wxBitmap& bitmap)
990 {
991 if ( m_maskBitmap )
992 {
993 wxMacDestroyGWorld( m_maskBitmap ) ;
994 m_maskBitmap = NULL ;
995 }
996 wxCHECK_MSG( bitmap.GetBitmapType() == kMacBitmapTypeGrafWorld, false,
997 wxT("Cannot create mask from this bitmap type (TODO)"));
998 // other types would require a temporary bitmap. not yet implemented
999
1000 wxCHECK_MSG( bitmap.Ok(), false, wxT("Invalid bitmap"));
1001
1002 wxCHECK_MSG(bitmap.GetDepth() == 1, false,
1003 wxT("Cannot create mask from colour bitmap"));
1004
1005 m_maskBitmap = wxMacCreateGWorld(bitmap.GetWidth(), bitmap.GetHeight(), 1);
1006 Rect rect = { 0,0, bitmap.GetHeight(), bitmap.GetWidth() };
1007
1008 LockPixels( GetGWorldPixMap(m_maskBitmap) );
1009 LockPixels( GetGWorldPixMap(bitmap.GetHBITMAP()) );
1010 CopyBits(GetPortBitMapForCopyBits(bitmap.GetHBITMAP()),
1011 GetPortBitMapForCopyBits(m_maskBitmap),
1012 &rect, &rect, srcCopy, 0);
1013 UnlockPixels( GetGWorldPixMap(m_maskBitmap) );
1014 UnlockPixels( GetGWorldPixMap(bitmap.GetHBITMAP()) );
1015
1016 return FALSE;
1017 }
1018
1019 // Create a mask from a bitmap and a palette index indicating
1020 // the transparent area
1021 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
1022 {
1023 // TODO
1024 wxCHECK_MSG( 0, false, wxT("Not implemented"));
1025 return FALSE;
1026 }
1027
1028 // Create a mask from a bitmap and a colour indicating
1029 // the transparent area
1030 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
1031 {
1032 if ( m_maskBitmap )
1033 {
1034 wxMacDestroyGWorld( m_maskBitmap ) ;
1035 m_maskBitmap = NULL ;
1036 }
1037 wxCHECK_MSG( bitmap.GetBitmapType() == kMacBitmapTypeGrafWorld, false,
1038 wxT("Cannot create mask from this bitmap type (TODO)"));
1039 // other types would require a temporary bitmap. not yet implemented
1040
1041 wxCHECK_MSG( bitmap.Ok(), false, wxT("Illigal bitmap"));
1042
1043 m_maskBitmap = wxMacCreateGWorld( bitmap.GetWidth() , bitmap.GetHeight() , 1 );
1044 LockPixels( GetGWorldPixMap( m_maskBitmap ) );
1045 LockPixels( GetGWorldPixMap( bitmap.GetHBITMAP() ) );
1046 RGBColor maskColor = colour.GetPixel();
1047
1048 // this is not very efficient, but I can't think
1049 // of a better way of doing it
1050 CGrafPtr origPort ;
1051 GDHandle origDevice ;
1052 RGBColor col;
1053 RGBColor colors[2] = {
1054 { 0xFFFF, 0xFFFF, 0xFFFF },
1055 { 0, 0, 0 }};
1056
1057 GetGWorld( &origPort , &origDevice ) ;
1058 for (int w = 0; w < bitmap.GetWidth(); w++)
1059 {
1060 for (int h = 0; h < bitmap.GetHeight(); h++)
1061 {
1062 SetGWorld( bitmap.GetHBITMAP(), NULL ) ;
1063 GetCPixel( w , h , &col ) ;
1064 SetGWorld( m_maskBitmap , NULL ) ;
1065 if (col.red == maskColor.red && col.green == maskColor.green && col.blue == maskColor.blue)
1066 {
1067 SetCPixel( w , h , &colors[0] ) ;
1068 }
1069 else
1070 {
1071 SetCPixel( w , h , &colors[1] ) ;
1072 }
1073 }
1074 }
1075 UnlockPixels( GetGWorldPixMap( (CGrafPtr) m_maskBitmap ) ) ;
1076 UnlockPixels( GetGWorldPixMap( bitmap.GetHBITMAP() ) ) ;
1077 SetGWorld( origPort , origDevice ) ;
1078
1079 return TRUE;
1080 }
1081
1082 bool wxMask::PointMasked(int x, int y)
1083 {
1084 WXHBITMAP origPort;
1085 GDHandle origDevice;
1086 RGBColor color;
1087 bool masked = true;
1088
1089 GetGWorld( &origPort, &origDevice);
1090
1091 //Set port to mask and see if it masked (1) or not ( 0 )
1092 SetGWorld(m_maskBitmap, NULL);
1093 LockPixels(GetGWorldPixMap(m_maskBitmap));
1094 GetCPixel(x,y, &color);
1095 masked = !(color.red == 0 && color.green == 0 && color.blue == 0);
1096 UnlockPixels(GetGWorldPixMap(m_maskBitmap));
1097
1098 SetGWorld( origPort, origDevice);
1099
1100 return masked;
1101 }
1102
1103 /*
1104 * wxBitmapHandler
1105 */
1106
1107 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
1108
1109 bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth)
1110 {
1111 return FALSE;
1112 }
1113
1114 bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long type,
1115 int desiredWidth, int desiredHeight)
1116 {
1117 return FALSE;
1118 }
1119
1120 bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
1121 {
1122 return FALSE;
1123 }
1124
1125 /*
1126 * Standard handlers
1127 */
1128
1129 class WXDLLEXPORT wxPICTResourceHandler: public wxBitmapHandler
1130 {
1131 DECLARE_DYNAMIC_CLASS(wxPICTResourceHandler)
1132 public:
1133 inline wxPICTResourceHandler()
1134 {
1135 m_name = "Macintosh Pict resource";
1136 m_extension = "";
1137 m_type = wxBITMAP_TYPE_PICT_RESOURCE;
1138 };
1139
1140 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1141 int desiredWidth, int desiredHeight);
1142 };
1143 IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler)
1144
1145 bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1146 int desiredWidth, int desiredHeight)
1147 {
1148 Str255 theName ;
1149
1150 #if TARGET_CARBON
1151 c2pstrcpy( (StringPtr) theName , name ) ;
1152 #else
1153 strcpy( (char *) theName , name ) ;
1154 c2pstr( (char *)theName ) ;
1155 #endif
1156
1157 PicHandle thePict = (PicHandle ) GetNamedResource( 'PICT' , theName ) ;
1158 if ( thePict )
1159 {
1160 PictInfo theInfo ;
1161
1162 GetPictInfo( thePict , &theInfo , 0 , 0 , systemMethod , 0 ) ;
1163 DetachResource( (Handle) thePict ) ;
1164 M_BITMAPHANDLERDATA->m_bitmapType = kMacBitmapTypePict ;
1165 M_BITMAPHANDLERDATA->m_hPict = thePict ;
1166 M_BITMAPHANDLERDATA->m_width = theInfo.sourceRect.right - theInfo.sourceRect.left ;
1167 M_BITMAPHANDLERDATA->m_height = theInfo.sourceRect.bottom - theInfo.sourceRect.top ;
1168
1169 M_BITMAPHANDLERDATA->m_depth = theInfo.depth ;
1170 M_BITMAPHANDLERDATA->m_ok = true ;
1171 M_BITMAPHANDLERDATA->m_numColors = theInfo.uniqueColors ;
1172 // M_BITMAPHANDLERDATA->m_bitmapPalette;
1173 // M_BITMAPHANDLERDATA->m_quality;
1174 return TRUE ;
1175 }
1176 return FALSE ;
1177 }
1178
1179 /* TODO: bitmap handlers, a bit like this:
1180 class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
1181 {
1182 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
1183 public:
1184 inline wxBMPResourceHandler()
1185 {
1186 m_name = "Windows bitmap resource";
1187 m_extension = "";
1188 m_type = wxBITMAP_TYPE_BMP_RESOURCE;
1189 };
1190
1191 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1192 int desiredWidth, int desiredHeight);
1193 };
1194 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
1195 */
1196
1197 class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
1198 {
1199 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
1200 public:
1201 inline wxXPMFileHandler(void)
1202 {
1203 m_name = "XPM bitmap file";
1204 m_extension = "xpm";
1205 m_type = wxBITMAP_TYPE_XPM;
1206 };
1207
1208 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1209 int desiredWidth = -1, int desiredHeight = -1);
1210 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
1211 };
1212 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
1213
1214 bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1215 int desiredWidth, int desiredHeight)
1216 {
1217 #if USE_XPM_IN_MSW
1218 XImage *ximage;
1219 XpmAttributes xpmAttr;
1220 HDC dc;
1221
1222 M_BITMAPHANDLERDATA->m_ok = FALSE;
1223 dc = CreateCompatibleDC(NULL);
1224 if (dc)
1225 {
1226 xpmAttr.valuemask = XpmReturnPixels;
1227 int errorStatus = XpmReadFileToImage(&dc, WXSTRINGCAST name, &ximage, (XImage **) NULL, &xpmAttr);
1228 DeleteDC(dc);
1229 if (errorStatus == XpmSuccess)
1230 {
1231 M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ximage->bitmap;
1232
1233 BITMAP bm;
1234 GetObject((HBITMAP)M_BITMAPHANDLERDATA->m_hBitmap, sizeof(bm), (LPSTR) & bm);
1235
1236 M_BITMAPHANDLERDATA->m_width = (bm.bmWidth);
1237 M_BITMAPHANDLERDATA->m_height = (bm.bmHeight);
1238 M_BITMAPHANDLERDATA->m_depth = (bm.bmPlanes * bm.bmBitsPixel);
1239 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
1240 XpmFreeAttributes(&xpmAttr);
1241 XImageFree(ximage);
1242
1243 M_BITMAPHANDLERDATA->m_ok = TRUE;
1244 return TRUE;
1245 }
1246 else
1247 {
1248 M_BITMAPHANDLERDATA->m_ok = FALSE;
1249 return FALSE;
1250 }
1251 }
1252 #endif
1253
1254 return FALSE;
1255 }
1256
1257 bool wxXPMFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
1258 {
1259 #if USE_XPM_IN_MSW
1260 HDC dc = NULL;
1261
1262 Visual *visual = NULL;
1263 XImage ximage;
1264
1265 dc = CreateCompatibleDC(NULL);
1266 if (dc)
1267 {
1268 if (SelectObject(dc, (HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap))
1269 {
1270
1271 ximage.width = M_BITMAPHANDLERDATA->m_width;
1272 ximage.height = M_BITMAPHANDLERDATA->m_height;
1273 ximage.depth = M_BITMAPHANDLERDATA->m_depth;
1274 ximage.bitmap = (void *)M_BITMAPHANDLERDATA->m_hBitmap;
1275 int errorStatus = XpmWriteFileFromImage(&dc, WXSTRINGCAST name,
1276 &ximage, (XImage *) NULL, (XpmAttributes *) NULL);
1277
1278 if (dc)
1279 DeleteDC(dc);
1280
1281 if (errorStatus == XpmSuccess)
1282 return TRUE;
1283 else
1284 return FALSE;
1285 } else return FALSE;
1286 } else return FALSE;
1287 #else
1288 return FALSE;
1289 #endif
1290 }
1291
1292 #ifdef OBSOLETE_XPM_DATA_HANDLER
1293 class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
1294 {
1295 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
1296 public:
1297 inline wxXPMDataHandler(void)
1298 {
1299 m_name = "XPM bitmap data";
1300 m_extension = "xpm";
1301 m_type = wxBITMAP_TYPE_XPM_DATA;
1302 };
1303
1304 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
1305 };
1306 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
1307
1308 bool wxXPMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth)
1309 {
1310 XImage * ximage = NULL ;
1311 XImage * xshapeimage = NULL ;
1312 int ErrorStatus;
1313 XpmAttributes xpmAttr;
1314
1315 xpmAttr.valuemask = XpmReturnInfos; // get infos back
1316 ErrorStatus = XpmCreateImageFromData( GetMainDevice() , (char **)data,
1317 &ximage, &xshapeimage, &xpmAttr);
1318
1319 if (ErrorStatus == XpmSuccess)
1320 {
1321 M_BITMAPHANDLERDATA->m_ok = FALSE;
1322 M_BITMAPHANDLERDATA->m_numColors = 0;
1323 M_BITMAPHANDLERDATA->m_hBitmap = ximage->gworldptr ;
1324
1325 M_BITMAPHANDLERDATA->m_width = ximage->width;
1326 M_BITMAPHANDLERDATA->m_height = ximage->height;
1327 M_BITMAPHANDLERDATA->m_depth = ximage->depth;
1328 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
1329 XpmFreeAttributes(&xpmAttr);
1330 M_BITMAPHANDLERDATA->m_ok = TRUE;
1331 ximage->gworldptr = NULL ;
1332 XImageFree(ximage); // releases the malloc, but does not detroy
1333 // the bitmap
1334 M_BITMAPHANDLERDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
1335 if ( xshapeimage != NULL )
1336 {
1337 wxMask* m = new wxMask() ;
1338 m->SetMaskBitmap( xshapeimage->gworldptr ) ;
1339 M_BITMAPHANDLERDATA->m_bitmapMask = m ;
1340 }
1341 return TRUE;
1342 }
1343 else
1344 {
1345 M_BITMAPHANDLERDATA->m_ok = FALSE;
1346 return FALSE;
1347 }
1348 return FALSE;
1349 }
1350 #endif
1351
1352 class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
1353 {
1354 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
1355 public:
1356 inline wxBMPResourceHandler()
1357 {
1358 m_name = "Windows bitmap resource";
1359 m_extension = "";
1360 m_type = wxBITMAP_TYPE_BMP_RESOURCE;
1361 };
1362
1363 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1364 int desiredWidth, int desiredHeight);
1365 };
1366
1367 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
1368
1369 bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1370 int desiredWidth, int desiredHeight)
1371 {
1372 // TODO: load colourmap.
1373 // it's probably not found
1374 wxLogError("Can't load bitmap '%s' from resources! Check .rc file.", name.c_str());
1375
1376 return FALSE;
1377 }
1378
1379 class WXDLLEXPORT wxBMPFileHandler: public wxBitmapHandler
1380 {
1381 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
1382 public:
1383 inline wxBMPFileHandler(void)
1384 {
1385 m_name = "Windows bitmap file";
1386 m_extension = "bmp";
1387 m_type = wxBITMAP_TYPE_BMP;
1388 };
1389
1390 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1391 int desiredWidth, int desiredHeight);
1392 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
1393 };
1394
1395 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
1396
1397 bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1398 int desiredWidth, int desiredHeight)
1399 {
1400 #if USE_IMAGE_LOADING_IN_MSW
1401 wxPalette *palette = NULL;
1402 bool success = FALSE;
1403 success = (wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0);
1404 if (!success && palette)
1405 {
1406 delete palette;
1407 palette = NULL;
1408 }
1409 if (palette)
1410 M_BITMAPHANDLERDATA->m_bitmapPalette = *palette;
1411 return success;
1412 #else
1413 return FALSE;
1414 #endif
1415 }
1416
1417 bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *pal)
1418 {
1419 #if USE_IMAGE_LOADING_IN_MSW
1420 wxPalette *actualPalette = (wxPalette *)pal;
1421 if (!actualPalette && (!M_BITMAPHANDLERDATA->m_bitmapPalette.IsNull()))
1422 actualPalette = & (M_BITMAPHANDLERDATA->m_bitmapPalette);
1423 return (wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0);
1424 #else
1425 return FALSE;
1426 #endif
1427 }
1428
1429
1430 void wxBitmap::CleanUpHandlers()
1431 {
1432 wxNode *node = sm_handlers.First();
1433 while ( node )
1434 {
1435 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
1436 wxNode *next = node->Next();
1437 delete handler;
1438 delete node;
1439 node = next;
1440 }
1441 }
1442
1443 void wxBitmap::InitStandardHandlers()
1444 {
1445 AddHandler(new wxPICTResourceHandler) ;
1446 AddHandler(new wxICONResourceHandler) ;
1447 AddHandler(new wxXPMFileHandler);
1448 #ifdef OBSOLETE_XPM_DATA_HANDLER
1449 AddHandler(new wxXPMDataHandler);
1450 #endif
1451 AddHandler(new wxBMPResourceHandler);
1452 AddHandler(new wxBMPFileHandler);
1453 }