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