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