]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/bitmap.cpp
corrected virtual function prototype
[wxWidgets.git] / src / mac / carbon / 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 #if !USE_SHARED_LIBRARIES
27 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
28 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
29 IMPLEMENT_ABSTRACT_CLASS(wxBitmapBase , wxGDIObject )
30 IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandlerBase, wxObject )
31 #endif
32
33 #ifdef __UNIX__
34 #include <ApplicationServices/ApplicationServices.h>
35 #else
36 #include <PictUtils.h>
37 #endif
38
39 #include "wx/mac/uma.h"
40
41 CTabHandle wxMacCreateColorTable( int numColors )
42 {
43 CTabHandle newColors; /* Handle to the new color table */
44
45 /* Allocate memory for the color table */
46 newColors = (CTabHandle)NewHandleClear( sizeof (ColorTable) +
47 sizeof (ColorSpec) * (numColors - 1) );
48 if (newColors != nil)
49 {
50 /* Initialize the fields */
51 (**newColors).ctSeed = GetCTSeed();
52 (**newColors).ctFlags = 0;
53 (**newColors).ctSize = numColors - 1;
54 /* Initialize the table of colors */
55 }
56 return newColors ;
57 }
58
59 void wxMacDestroyColorTable( CTabHandle colors )
60 {
61 DisposeHandle( (Handle) colors ) ;
62 }
63
64 void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue )
65 {
66 (**newColors).ctTable[index].value = index;
67 (**newColors).ctTable[index].rgb.red = 0 ;// someRedValue;
68 (**newColors).ctTable[index].rgb.green = 0 ; // someGreenValue;
69 (**newColors).ctTable[index].rgb.blue = 0 ; // someBlueValue;
70 }
71
72 GWorldPtr wxMacCreateGWorld( int width , int height , int depth )
73 {
74 OSErr err = noErr ;
75 GWorldPtr port ;
76 Rect rect = { 0 , 0 , height , width } ;
77
78 if ( depth < 0 )
79 {
80 depth = wxDisplayDepth() ;
81 }
82
83 err = NewGWorld( &port , depth , &rect , NULL , NULL , 0 ) ;
84 if ( err == noErr )
85 {
86 return port ;
87 }
88 return NULL ;
89 }
90
91 void wxMacDestroyGWorld( GWorldPtr gw )
92 {
93 if ( gw )
94 DisposeGWorld( gw ) ;
95 }
96
97 PicHandle wxMacCreatePict(GWorldPtr wp, GWorldPtr mask)
98 {
99 CGrafPtr origPort ;
100 GDHandle origDev ;
101
102 PicHandle pict; // this is the Picture we give back
103
104 RGBColor gray = { 0xCCCC ,0xCCCC , 0xCCCC } ;
105 RGBColor white = { 0xffff ,0xffff , 0xffff } ;
106 RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ;
107
108 unsigned char *maskimage = NULL ;
109 Rect portRect ;
110 GetPortBounds( wp , &portRect ) ;
111 int width = portRect.right - portRect.left ;
112 int height = portRect.bottom - portRect.top ;
113
114 LockPixels( GetGWorldPixMap( wp ) ) ;
115 GetGWorld( &origPort , &origDev ) ;
116
117 if ( mask )
118 {
119 maskimage = (unsigned char*) malloc( width * height ) ;
120 SetGWorld( mask , NULL ) ;
121 LockPixels( GetGWorldPixMap( mask ) ) ;
122 for ( int y = 0 ; y < height ; y++ )
123 {
124 for( int x = 0 ; x < width ; x++ )
125 {
126 RGBColor col ;
127
128 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
129 maskimage[y*width + x] = ( col.red == 0 ) ; // for monochrome masks
130 }
131 }
132 UnlockPixels( GetGWorldPixMap( mask ) ) ;
133 }
134
135 SetGWorld( wp , NULL ) ;
136
137 pict = OpenPicture(&portRect); // open a picture, this disables drawing
138 if(!pict)
139 return NULL;
140
141 if ( maskimage )
142 {
143 RGBForeColor( &black ) ;
144 RGBBackColor( &white ) ;
145 PenMode(transparent);
146
147 for ( int y = 0 ; y < height ; ++y )
148 {
149 for( int x = 0 ; x < width ; ++x )
150 {
151 if ( maskimage[y*width + x] )
152 {
153 RGBColor col ;
154
155 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
156 SetCPixel( x + portRect.left , y + portRect.top , &col ) ;
157 }
158 else {
159 // With transparency set this sets a blank pixel not a white one
160 SetCPixel( x + portRect.left , y + portRect.top , &white);
161 }
162 }
163 }
164 free( maskimage ) ;
165 maskimage = NULL ;
166 }
167 else
168 {
169 RGBBackColor( &gray ) ;
170 EraseRect(&portRect);
171 RGBForeColor( &black ) ;
172 RGBBackColor( &white ) ;
173
174 CopyBits(GetPortBitMapForCopyBits(wp), /* src PixMap - we copy image over
175 * itself - */
176 GetPortBitMapForCopyBits(wp), // dst PixMap - no drawing occurs
177 &portRect, // srcRect - it will be recorded and compressed -
178 &portRect, // dstRect - into the picture that is open -
179 srcCopy,NULL); // copyMode and no clip region
180 }
181 ClosePicture(); // We are done recording the picture
182 UnlockPixels( GetGWorldPixMap( wp ) ) ;
183 SetGWorld( origPort , origDev ) ;
184
185 return pict; // return our groovy pict handle
186 }
187
188 wxBitmapRefData::wxBitmapRefData()
189 {
190 m_ok = FALSE;
191 m_width = 0;
192 m_height = 0;
193 m_depth = 0;
194 m_quality = 0;
195 m_numColors = 0;
196 m_bitmapMask = NULL;
197 m_hBitmap = NULL ;
198 m_hPict = NULL ;
199 m_hIcon = NULL ;
200 m_bitmapType = kMacBitmapTypeUnknownType ;
201 }
202
203 wxBitmapRefData::~wxBitmapRefData()
204 {
205 switch (m_bitmapType)
206 {
207 case kMacBitmapTypePict :
208 {
209 if ( m_hPict )
210 {
211 KillPicture( m_hPict ) ;
212 m_hPict = NULL ;
213 }
214 }
215 break ;
216 case kMacBitmapTypeGrafWorld :
217 {
218 if ( m_hBitmap )
219 {
220 wxMacDestroyGWorld( m_hBitmap ) ;
221 m_hBitmap = NULL ;
222 }
223 }
224 break ;
225 case kMacBitmapTypeIcon :
226 if ( m_hIcon )
227 {
228 DisposeCIcon( m_hIcon ) ;
229 m_hIcon = NULL ;
230 }
231
232 default :
233 // unkown type ?
234 break ;
235 }
236
237 if (m_bitmapMask)
238 {
239 delete m_bitmapMask;
240 m_bitmapMask = NULL;
241 }
242 }
243
244 wxList wxBitmap::sm_handlers;
245
246
247 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
248 {
249 Ref(icon) ;
250 }
251
252 wxBitmap::wxBitmap()
253 {
254 m_refData = NULL;
255
256 if ( wxTheBitmapList )
257 wxTheBitmapList->AddBitmap(this);
258 }
259
260 wxBitmap::~wxBitmap()
261 {
262 if (wxTheBitmapList)
263 wxTheBitmapList->DeleteObject(this);
264 }
265
266 wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
267 {
268 m_refData = new wxBitmapRefData;
269
270 M_BITMAPDATA->m_width = the_width ;
271 M_BITMAPDATA->m_height = the_height ;
272 M_BITMAPDATA->m_depth = no_bits ;
273 M_BITMAPDATA->m_numColors = 0;
274 if ( no_bits == 1 )
275 {
276 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
277 M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( the_width , the_height , no_bits ) ;
278 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
279
280 CGrafPtr origPort ;
281 GDHandle origDevice ;
282
283 GetGWorld( &origPort , &origDevice ) ;
284 SetGWorld( M_BITMAPDATA->m_hBitmap , NULL ) ;
285 LockPixels( GetGWorldPixMap( M_BITMAPDATA->m_hBitmap ) ) ;
286
287 // bits is a char array
288
289 unsigned char* linestart = (unsigned char*) bits ;
290 int linesize = ( the_width / (sizeof(unsigned char) * 8)) ;
291 if ( the_width % (sizeof(unsigned char) * 8) ) {
292 linesize += sizeof(unsigned char);
293 }
294
295 RGBColor colors[2] = {
296 { 0xFFFF , 0xFFFF , 0xFFFF } ,
297 { 0, 0 , 0 }
298 } ;
299
300 for ( int y = 0 ; y < the_height ; ++y , linestart += linesize )
301 {
302 for ( int x = 0 ; x < the_width ; ++x )
303 {
304 int index = x / 8 ;
305 int bit = x % 8 ;
306 int mask = 1 << bit ;
307 if ( linestart[index] & mask )
308 {
309 SetCPixel( x , y , &colors[1] ) ;
310 }
311 else
312 {
313 SetCPixel( x , y , &colors[0] ) ;
314 }
315 }
316 }
317 UnlockPixels( GetGWorldPixMap( M_BITMAPDATA->m_hBitmap ) ) ;
318
319 SetGWorld( origPort , origDevice ) ;
320 }
321 else
322 {
323 wxFAIL_MSG(wxT("multicolor BITMAPs not yet implemented"));
324 }
325
326 if ( wxTheBitmapList ) {
327 wxTheBitmapList->AddBitmap(this);
328 }
329 }
330
331 wxBitmap::wxBitmap(int w, int h, int d)
332 {
333 (void)Create(w, h, d);
334
335 if ( wxTheBitmapList )
336 wxTheBitmapList->AddBitmap(this);
337 }
338
339 wxBitmap::wxBitmap(void *data, wxBitmapType type, int width, int height, int depth)
340 {
341 (void) Create(data, type, width, height, depth);
342
343 if ( wxTheBitmapList )
344 wxTheBitmapList->AddBitmap(this);
345 }
346
347 wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
348 {
349 LoadFile(filename, type);
350
351 if ( wxTheBitmapList )
352 wxTheBitmapList->AddBitmap(this);
353 }
354
355 bool wxBitmap::CreateFromXpm(const char **bits)
356 {
357 wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") )
358 wxXPMDecoder decoder;
359 wxImage img = decoder.ReadData(bits);
360 wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid bitmap data") )
361 *this = wxBitmap(img);
362 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
363 return TRUE;
364 }
365
366 wxBitmap::wxBitmap(const char **bits)
367 {
368 (void) CreateFromXpm(bits);
369 }
370
371 wxBitmap::wxBitmap(char **bits)
372 {
373 (void) CreateFromXpm((const char **)bits);
374 }
375
376 wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const
377 {
378 wxCHECK_MSG( Ok() &&
379 (rect.x >= 0) && (rect.y >= 0) &&
380 (rect.x+rect.width <= GetWidth()) &&
381 (rect.y+rect.height <= GetHeight()),
382 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
383
384
385 wxBitmap ret( rect.width, rect.height, GetDepth() );
386 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
387
388 WXHBITMAP origPort;
389 GDHandle origDevice;
390
391 GetGWorld( &origPort, &origDevice );
392
393 // Update the subbitmaps reference data
394 wxBitmapRefData *ref = (wxBitmapRefData *)ret.GetRefData();
395
396 ref->m_numColors = M_BITMAPDATA->m_numColors;
397 ref->m_bitmapPalette = M_BITMAPDATA->m_bitmapPalette;
398 ref->m_bitmapType = M_BITMAPDATA->m_bitmapType;
399
400 // Copy sub region of this bitmap
401 if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypePict)
402 {
403 printf("GetSubBitmap: Copy a region of a Pict structure - TODO\n");
404 }
405 else if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypeGrafWorld)
406 {
407 // Copy mask
408 if(GetMask())
409 {
410 WXHBITMAP submask, mask;
411 RGBColor color;
412
413 mask = GetMask()->GetMaskBitmap();
414 submask = wxMacCreateGWorld(rect.width, rect.height, 1);
415 LockPixels(GetGWorldPixMap(mask));
416 LockPixels(GetGWorldPixMap(submask));
417
418 for(int yy = 0; yy < rect.height; yy++)
419 {
420 for(int xx = 0; xx < rect.width; xx++)
421 {
422 SetGWorld(mask, NULL);
423 GetCPixel(rect.x + xx, rect.y + yy, &color);
424 SetGWorld(submask, NULL);
425 SetCPixel(xx,yy, &color);
426 }
427 }
428 UnlockPixels(GetGWorldPixMap(mask));
429 UnlockPixels(GetGWorldPixMap(submask));
430 ref->m_bitmapMask = new wxMask;
431 ref->m_bitmapMask->SetMaskBitmap(submask);
432 }
433
434 // Copy bitmap
435 if(GetHBITMAP())
436 {
437 WXHBITMAP subbitmap, bitmap;
438 RGBColor color;
439
440 bitmap = GetHBITMAP();
441 subbitmap = wxMacCreateGWorld(rect.width, rect.height, GetDepth());
442 LockPixels(GetGWorldPixMap(bitmap));
443 LockPixels(GetGWorldPixMap(subbitmap));
444
445 for(int yy = 0; yy < rect.height; yy++)
446 {
447 for(int xx = 0; xx < rect.width; xx++)
448 {
449 SetGWorld(bitmap, NULL);
450 GetCPixel(rect.x + xx, rect.y + yy, &color);
451 SetGWorld(subbitmap, NULL);
452 SetCPixel(xx, yy, &color);
453 }
454 }
455 UnlockPixels(GetGWorldPixMap(bitmap));
456 UnlockPixels(GetGWorldPixMap(subbitmap));
457 ret.SetHBITMAP(subbitmap);
458 }
459 }
460 SetGWorld( origPort, origDevice );
461
462 return ret;
463 }
464
465 bool wxBitmap::Create(int w, int h, int d)
466 {
467 UnRef();
468
469 m_refData = new wxBitmapRefData;
470
471 M_BITMAPDATA->m_width = w;
472 M_BITMAPDATA->m_height = h;
473 M_BITMAPDATA->m_depth = d;
474
475 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
476 M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( w , h , d ) ;
477 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
478 return M_BITMAPDATA->m_ok;
479 }
480
481 int wxBitmap::GetBitmapType() const
482 {
483 wxCHECK_MSG( Ok(), kMacBitmapTypeUnknownType, wxT("invalid bitmap") );
484
485 return M_BITMAPDATA->m_bitmapType;
486 }
487
488 void wxBitmap::SetHBITMAP(WXHBITMAP bmp)
489 {
490 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
491 M_BITMAPDATA->m_hBitmap = bmp ;
492 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
493 }
494
495 bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
496 {
497 UnRef();
498
499 wxBitmapHandler *handler = FindHandler(type);
500
501 if ( handler )
502 {
503 m_refData = new wxBitmapRefData;
504
505 return handler->LoadFile(this, filename, type, -1, -1);
506 }
507 else
508 {
509 wxImage loadimage(filename, type);
510 if (loadimage.Ok()) {
511 *this = loadimage;
512 return true;
513 }
514 }
515 wxLogWarning("no bitmap handler for type %d defined.", type);
516 return false;
517 }
518
519 bool wxBitmap::Create(void *data, wxBitmapType 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, wxBitmapType type,
671 const wxPalette *palette) const
672 {
673 wxBitmapHandler *handler = FindHandler(type);
674
675 if ( handler )
676 {
677 return handler->SaveFile(this, filename, type, palette);
678 }
679 else
680 {
681 wxImage image = ConvertToImage();
682
683 return image.SaveFile(filename, type);
684 }
685
686 wxLogWarning("no bitmap handler for type %d defined.", type);
687 return false;
688 }
689
690 bool wxBitmap::Ok() const
691 {
692 return (M_BITMAPDATA && M_BITMAPDATA->m_ok);
693 }
694
695 int wxBitmap::GetHeight() const
696 {
697 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
698
699 return M_BITMAPDATA->m_height;
700 }
701
702 int wxBitmap::GetWidth() const
703 {
704 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
705
706 return M_BITMAPDATA->m_width;
707 }
708
709 int wxBitmap::GetDepth() const
710 {
711 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
712
713 return M_BITMAPDATA->m_depth;
714 }
715
716 int wxBitmap::GetQuality() const
717 {
718 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
719
720 return M_BITMAPDATA->m_quality;
721 }
722
723 wxMask *wxBitmap::GetMask() const
724 {
725 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
726
727 return M_BITMAPDATA->m_bitmapMask;
728 }
729
730 void wxBitmap::SetWidth(int w)
731 {
732 if (!M_BITMAPDATA)
733 m_refData = new wxBitmapRefData;
734
735 M_BITMAPDATA->m_width = w;
736 }
737
738 void wxBitmap::SetHeight(int h)
739 {
740 if (!M_BITMAPDATA)
741 m_refData = new wxBitmapRefData;
742
743 M_BITMAPDATA->m_height = h;
744 }
745
746 void wxBitmap::SetDepth(int d)
747 {
748 if (!M_BITMAPDATA)
749 m_refData = new wxBitmapRefData;
750
751 M_BITMAPDATA->m_depth = d;
752 }
753
754 void wxBitmap::SetQuality(int q)
755 {
756 if (!M_BITMAPDATA)
757 m_refData = new wxBitmapRefData;
758
759 M_BITMAPDATA->m_quality = q;
760 }
761
762 void wxBitmap::SetOk(bool isOk)
763 {
764 if (!M_BITMAPDATA)
765 m_refData = new wxBitmapRefData;
766
767 M_BITMAPDATA->m_ok = isOk;
768 }
769
770 wxPalette *wxBitmap::GetPalette() const
771 {
772 wxCHECK_MSG( Ok(), NULL, wxT("Invalid bitmap GetPalette()") );
773
774 return &M_BITMAPDATA->m_bitmapPalette;
775 }
776
777 void wxBitmap::SetPalette(const wxPalette& palette)
778 {
779 if (!M_BITMAPDATA)
780 m_refData = new wxBitmapRefData;
781
782 M_BITMAPDATA->m_bitmapPalette = palette ;
783 }
784
785 void wxBitmap::SetMask(wxMask *mask)
786 {
787 if (!M_BITMAPDATA)
788 m_refData = new wxBitmapRefData;
789
790 // Remove existing mask if there is one.
791 if (M_BITMAPDATA->m_bitmapMask)
792 delete M_BITMAPDATA->m_bitmapMask;
793
794 M_BITMAPDATA->m_bitmapMask = mask ;
795 }
796
797 WXHBITMAP wxBitmap::GetHBITMAP() const
798 {
799 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
800
801 return M_BITMAPDATA->m_hBitmap;
802 }
803
804 PicHandle wxBitmap::GetPict() const
805 {
806 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
807
808 PicHandle picture; // This is the returned picture
809
810 // If bitmap already in Pict format return pointer
811 if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypePict) {
812 return M_BITMAPDATA->m_hPict;
813 }
814 else if(M_BITMAPDATA->m_bitmapType != kMacBitmapTypeGrafWorld) {
815 // Invalid bitmap
816 return NULL;
817 }
818
819 RGBColor gray = { 0xCCCC ,0xCCCC , 0xCCCC } ;
820 RGBColor white = { 0xffff ,0xffff , 0xffff } ;
821 RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ;
822 CGrafPtr origPort;
823 GDHandle origDev ;
824 wxMask *mask;
825 Rect portRect ;
826
827 GetPortBounds( GetHBITMAP() , &portRect ) ;
828 int width = portRect.right - portRect.left ;
829 int height = portRect.bottom - portRect.top ;
830
831 LockPixels( GetGWorldPixMap( GetHBITMAP() ) ) ;
832 GetGWorld( &origPort , &origDev ) ;
833
834 mask = GetMask();
835
836 SetGWorld( GetHBITMAP() , NULL ) ;
837
838 picture = OpenPicture(&portRect); // open a picture, this disables drawing
839 if(!picture) {
840 return NULL;
841 }
842
843 if( mask )
844 {
845 #ifdef __UNIX__
846 RGBColor trans = white;
847 #else
848 RGBBackColor( &gray );
849 EraseRect( &portRect );
850 RGBColor trans = gray;
851 #endif
852 RGBForeColor( &black ) ;
853 RGBBackColor( &white ) ;
854 PenMode(transparent);
855
856 for ( int y = 0 ; y < height ; ++y )
857 {
858 for( int x = 0 ; x < width ; ++x )
859 {
860 if ( !mask->PointMasked(x,y) )
861 {
862 RGBColor col ;
863
864 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
865 SetCPixel( x + portRect.left , y + portRect.top , &col ) ;
866 }
867 else {
868 // With transparency this sets a blank pixel
869 SetCPixel( x + portRect.left , y + portRect.top , &trans);
870 }
871 }
872 }
873 }
874 else
875 {
876 RGBBackColor( &gray ) ;
877 EraseRect(&portRect);
878 RGBForeColor( &black ) ;
879 RGBBackColor( &white ) ;
880
881 CopyBits(GetPortBitMapForCopyBits(GetHBITMAP()),
882 // src PixMap - we copy image over itself -
883 GetPortBitMapForCopyBits(GetHBITMAP()),
884 // dst PixMap - no drawing occurs
885 &portRect, // srcRect - it will be recorded and compressed -
886 &portRect, // dstRect - into the picture that is open -
887 srcCopy,NULL); // copyMode and no clip region
888 }
889 ClosePicture(); // We are done recording the picture
890 UnlockPixels( GetGWorldPixMap( GetHBITMAP() ) ) ;
891 SetGWorld( origPort , origDev ) ;
892
893 return picture; // return our groovy pict handle
894 }
895
896 void wxBitmap::AddHandler(wxBitmapHandler *handler)
897 {
898 sm_handlers.Append(handler);
899 }
900
901 void wxBitmap::InsertHandler(wxBitmapHandler *handler)
902 {
903 sm_handlers.Insert(handler);
904 }
905
906 bool wxBitmap::RemoveHandler(const wxString& name)
907 {
908 wxBitmapHandler *handler = FindHandler(name);
909 if ( handler )
910 {
911 sm_handlers.DeleteObject(handler);
912 return TRUE;
913 }
914 else
915 return FALSE;
916 }
917
918 wxBitmapHandler *wxBitmap::FindHandler(const wxString& name)
919 {
920 wxNode *node = sm_handlers.First();
921 while ( node )
922 {
923 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
924 if ( handler->GetName() == name )
925 return handler;
926 node = node->Next();
927 }
928 return NULL;
929 }
930
931 wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, wxBitmapType type)
932 {
933 wxNode *node = sm_handlers.First();
934 while ( node )
935 {
936 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
937 if ( handler->GetExtension() == extension &&
938 (type == -1 || handler->GetType() == type) )
939 return handler;
940 node = node->Next();
941 }
942 return NULL;
943 }
944
945 wxBitmapHandler *wxBitmap::FindHandler(wxBitmapType type)
946 {
947 wxNode *node = sm_handlers.First();
948 while ( node )
949 {
950 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
951 if (handler->GetType() == type)
952 return handler;
953 node = node->Next();
954 }
955 return NULL;
956 }
957
958 /*
959 * wxMask
960 */
961
962 wxMask::wxMask()
963 {
964 m_maskBitmap = 0;
965 }
966
967 // Construct a mask from a bitmap and a colour indicating
968 // the transparent area
969 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
970 {
971 m_maskBitmap = 0;
972 Create(bitmap, colour);
973 }
974
975 // Construct a mask from a bitmap and a palette index indicating
976 // the transparent area
977 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
978 {
979 m_maskBitmap = 0;
980 Create(bitmap, paletteIndex);
981 }
982
983 // Construct a mask from a mono bitmap (copies the bitmap).
984 wxMask::wxMask(const wxBitmap& bitmap)
985 {
986 m_maskBitmap = 0;
987 Create(bitmap);
988 }
989
990 wxMask::~wxMask()
991 {
992 if ( m_maskBitmap )
993 {
994 wxMacDestroyGWorld( m_maskBitmap ) ;
995 m_maskBitmap = NULL ;
996 }
997 }
998
999 // Create a mask from a mono bitmap (copies the bitmap).
1000 bool wxMask::Create(const wxBitmap& bitmap)
1001 {
1002 if ( m_maskBitmap )
1003 {
1004 wxMacDestroyGWorld( m_maskBitmap ) ;
1005 m_maskBitmap = NULL ;
1006 }
1007 wxCHECK_MSG( bitmap.GetBitmapType() == kMacBitmapTypeGrafWorld, false,
1008 wxT("Cannot create mask from this bitmap type (TODO)"));
1009 // other types would require a temporary bitmap. not yet implemented
1010
1011 wxCHECK_MSG( bitmap.Ok(), false, wxT("Invalid bitmap"));
1012
1013 wxCHECK_MSG(bitmap.GetDepth() == 1, false,
1014 wxT("Cannot create mask from colour bitmap"));
1015
1016 m_maskBitmap = wxMacCreateGWorld(bitmap.GetWidth(), bitmap.GetHeight(), 1);
1017 Rect rect = { 0,0, bitmap.GetHeight(), bitmap.GetWidth() };
1018
1019 LockPixels( GetGWorldPixMap(m_maskBitmap) );
1020 LockPixels( GetGWorldPixMap(bitmap.GetHBITMAP()) );
1021 CopyBits(GetPortBitMapForCopyBits(bitmap.GetHBITMAP()),
1022 GetPortBitMapForCopyBits(m_maskBitmap),
1023 &rect, &rect, srcCopy, 0);
1024 UnlockPixels( GetGWorldPixMap(m_maskBitmap) );
1025 UnlockPixels( GetGWorldPixMap(bitmap.GetHBITMAP()) );
1026
1027 return FALSE;
1028 }
1029
1030 // Create a mask from a bitmap and a palette index indicating
1031 // the transparent area
1032 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
1033 {
1034 // TODO
1035 wxCHECK_MSG( 0, false, wxT("Not implemented"));
1036 return FALSE;
1037 }
1038
1039 // Create a mask from a bitmap and a colour indicating
1040 // the transparent area
1041 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
1042 {
1043 if ( m_maskBitmap )
1044 {
1045 wxMacDestroyGWorld( m_maskBitmap ) ;
1046 m_maskBitmap = NULL ;
1047 }
1048 wxCHECK_MSG( bitmap.GetBitmapType() == kMacBitmapTypeGrafWorld, false,
1049 wxT("Cannot create mask from this bitmap type (TODO)"));
1050 // other types would require a temporary bitmap. not yet implemented
1051
1052 wxCHECK_MSG( bitmap.Ok(), false, wxT("Illigal bitmap"));
1053
1054 m_maskBitmap = wxMacCreateGWorld( bitmap.GetWidth() , bitmap.GetHeight() , 1 );
1055 LockPixels( GetGWorldPixMap( m_maskBitmap ) );
1056 LockPixels( GetGWorldPixMap( bitmap.GetHBITMAP() ) );
1057 RGBColor maskColor = colour.GetPixel();
1058
1059 // this is not very efficient, but I can't think
1060 // of a better way of doing it
1061 CGrafPtr origPort ;
1062 GDHandle origDevice ;
1063 RGBColor col;
1064 RGBColor colors[2] = {
1065 { 0xFFFF, 0xFFFF, 0xFFFF },
1066 { 0, 0, 0 }};
1067
1068 GetGWorld( &origPort , &origDevice ) ;
1069 for (int w = 0; w < bitmap.GetWidth(); w++)
1070 {
1071 for (int h = 0; h < bitmap.GetHeight(); h++)
1072 {
1073 SetGWorld( bitmap.GetHBITMAP(), NULL ) ;
1074 GetCPixel( w , h , &col ) ;
1075 SetGWorld( m_maskBitmap , NULL ) ;
1076 if (col.red == maskColor.red && col.green == maskColor.green && col.blue == maskColor.blue)
1077 {
1078 SetCPixel( w , h , &colors[0] ) ;
1079 }
1080 else
1081 {
1082 SetCPixel( w , h , &colors[1] ) ;
1083 }
1084 }
1085 }
1086 UnlockPixels( GetGWorldPixMap( (CGrafPtr) m_maskBitmap ) ) ;
1087 UnlockPixels( GetGWorldPixMap( bitmap.GetHBITMAP() ) ) ;
1088 SetGWorld( origPort , origDevice ) ;
1089
1090 return TRUE;
1091 }
1092
1093 bool wxMask::PointMasked(int x, int y)
1094 {
1095 WXHBITMAP origPort;
1096 GDHandle origDevice;
1097 RGBColor color;
1098 bool masked = true;
1099
1100 GetGWorld( &origPort, &origDevice);
1101
1102 //Set port to mask and see if it masked (1) or not ( 0 )
1103 SetGWorld(m_maskBitmap, NULL);
1104 LockPixels(GetGWorldPixMap(m_maskBitmap));
1105 GetCPixel(x,y, &color);
1106 masked = !(color.red == 0 && color.green == 0 && color.blue == 0);
1107 UnlockPixels(GetGWorldPixMap(m_maskBitmap));
1108
1109 SetGWorld( origPort, origDevice);
1110
1111 return masked;
1112 }
1113
1114 /*
1115 * wxBitmapHandler
1116 */
1117
1118 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
1119
1120 bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth)
1121 {
1122 return FALSE;
1123 }
1124
1125 bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1126 int desiredWidth, int desiredHeight)
1127 {
1128 return FALSE;
1129 }
1130
1131 bool wxBitmapHandler::SaveFile(const wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
1132 {
1133 return FALSE;
1134 }
1135
1136 /*
1137 * Standard handlers
1138 */
1139
1140 class WXDLLEXPORT wxPICTResourceHandler: public wxBitmapHandler
1141 {
1142 DECLARE_DYNAMIC_CLASS(wxPICTResourceHandler)
1143 public:
1144 inline wxPICTResourceHandler()
1145 {
1146 m_name = "Macintosh Pict resource";
1147 m_extension = "";
1148 m_type = wxBITMAP_TYPE_PICT_RESOURCE;
1149 };
1150
1151 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1152 int desiredWidth, int desiredHeight);
1153 };
1154 IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler)
1155
1156 bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1157 int desiredWidth, int desiredHeight)
1158 {
1159 Str255 theName ;
1160
1161 #if TARGET_CARBON
1162 c2pstrcpy( (StringPtr) theName , name ) ;
1163 #else
1164 strcpy( (char *) theName , name ) ;
1165 c2pstr( (char *)theName ) ;
1166 #endif
1167
1168 PicHandle thePict = (PicHandle ) GetNamedResource( 'PICT' , theName ) ;
1169 if ( thePict )
1170 {
1171 PictInfo theInfo ;
1172
1173 GetPictInfo( thePict , &theInfo , 0 , 0 , systemMethod , 0 ) ;
1174 DetachResource( (Handle) thePict ) ;
1175 M_BITMAPHANDLERDATA->m_bitmapType = kMacBitmapTypePict ;
1176 M_BITMAPHANDLERDATA->m_hPict = thePict ;
1177 M_BITMAPHANDLERDATA->m_width = theInfo.sourceRect.right - theInfo.sourceRect.left ;
1178 M_BITMAPHANDLERDATA->m_height = theInfo.sourceRect.bottom - theInfo.sourceRect.top ;
1179
1180 M_BITMAPHANDLERDATA->m_depth = theInfo.depth ;
1181 M_BITMAPHANDLERDATA->m_ok = true ;
1182 M_BITMAPHANDLERDATA->m_numColors = theInfo.uniqueColors ;
1183 // M_BITMAPHANDLERDATA->m_bitmapPalette;
1184 // M_BITMAPHANDLERDATA->m_quality;
1185 return TRUE ;
1186 }
1187 return FALSE ;
1188 }
1189
1190 #if 0 // The following is an example for creating a bitmap handler
1191
1192 // TODO: bitmap handlers, a bit like this:
1193 class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
1194 {
1195 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
1196 public:
1197 inline wxBMPResourceHandler()
1198 {
1199 m_name = "Windows bitmap resource";
1200 m_extension = "";
1201 m_type = wxBITMAP_TYPE_BMP_RESOURCE;
1202 };
1203
1204 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1205 int desiredWidth, int desiredHeight);
1206 };
1207 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
1208
1209 #endif
1210
1211 void wxBitmap::CleanUpHandlers()
1212 {
1213 wxNode *node = sm_handlers.First();
1214 while ( node )
1215 {
1216 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
1217 wxNode *next = node->Next();
1218 delete handler;
1219 delete node;
1220 node = next;
1221 }
1222 }
1223
1224 void wxBitmap::InitStandardHandlers()
1225 {
1226 AddHandler(new wxPICTResourceHandler) ;
1227 AddHandler(new wxICONResourceHandler) ;
1228 }