]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/bitmap.cpp
make sure we catch invalid control refs better
[wxWidgets.git] / src / mac / carbon / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/bitmap.cpp
3 // Purpose: wxBitmap
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include "wx/bitmap.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/log.h"
18 #include "wx/dcmemory.h"
19 #include "wx/icon.h"
20 #include "wx/image.h"
21 #endif
22
23 #include "wx/metafile.h"
24 #include "wx/xpmdecod.h"
25
26 #include "wx/rawbmp.h"
27
28 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
29 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
30 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
31
32 #ifdef __DARWIN__
33 #include <ApplicationServices/ApplicationServices.h>
34 #else
35 #include <PictUtils.h>
36 #endif
37
38 #include "wx/mac/uma.h"
39
40 // Implementation Notes
41 // --------------------
42 //
43 // we are always working with a 32 bit deep pixel buffer
44 // under QuickDraw its alpha parts are going to be ignored in the GWorld,
45 // therefore we have a separate GWorld there for blitting the mask in
46
47 // under Quartz then content is transformed into a CGImageRef representing the same data
48 // which can be transferred to the GPU by the OS for fast rendering
49
50 // we don't dare use premultiplied alpha yet
51 #define wxMAC_USE_PREMULTIPLIED_ALPHA 0
52
53 #if wxUSE_BMPBUTTON
54
55 void wxMacCreateBitmapButton( ControlButtonContentInfo*info , const wxBitmap& bitmap , int forceType )
56 {
57 memset( info , 0 , sizeof(ControlButtonContentInfo) ) ;
58 if ( bitmap.Ok() )
59 {
60 wxBitmapRefData * bmap = bitmap.GetBitmapData() ;
61 if ( bmap == NULL )
62 return ;
63
64 if ( ( bmap->HasNativeSize() && forceType == 0 ) || forceType == kControlContentIconRef )
65 {
66 wxBitmap scaleBmp ;
67 wxBitmapRefData* bmp = bmap ;
68
69 if ( !bmap->HasNativeSize() )
70 {
71 // as PICT conversion will only result in a 16x16 icon, let's attempt
72 // a few scales for better results
73
74 int w = bitmap.GetWidth() ;
75 int h = bitmap.GetHeight() ;
76 int sz = wxMax( w , h ) ;
77 if ( sz == 24 || sz == 64 )
78 {
79 scaleBmp = wxBitmap( bitmap.ConvertToImage().Scale( w * 2 , h * 2 ) ) ;
80 bmp = scaleBmp.GetBitmapData() ;
81 }
82 }
83
84 info->contentType = kControlContentIconRef ;
85 info->u.iconRef = bmp->GetIconRef() ;
86 AcquireIconRef( info->u.iconRef ) ;
87 }
88 #if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
89 else if ( forceType == kControlContentCGImageRef )
90 {
91 info->contentType = kControlContentCGImageRef ;
92 info->u.imageRef = (CGImageRef) bmap->CGImageCreate() ;
93 }
94 #endif
95 else
96 {
97 info->contentType = kControlContentPictHandle ;
98 info->u.picture = bmap->GetPictHandle() ;
99 }
100 }
101 }
102
103 void wxMacReleaseBitmapButton( ControlButtonContentInfo*info )
104 {
105 if ( info->contentType == kControlContentIconRef )
106 {
107 ReleaseIconRef( info->u.iconRef ) ;
108 }
109 else if ( info->contentType == kControlNoContent )
110 {
111 // there's no bitmap at all, fall through silently
112 }
113 else if ( info->contentType == kControlContentPictHandle )
114 {
115 // owned by the bitmap, no release here
116 }
117 #if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
118 else if ( info->contentType == kControlContentCGImageRef )
119 {
120 CGImageRelease( info->u.imageRef ) ;
121 }
122 #endif
123 else
124 {
125 wxFAIL_MSG(wxT("Unexpected bitmap type") ) ;
126 }
127 }
128
129 #endif //wxUSE_BMPBUTTON
130
131 #define M_BITMAPDATA ((wxBitmapRefData *)m_refData)
132
133 void wxBitmapRefData::Init()
134 {
135 m_width = 0 ;
136 m_height = 0 ;
137 m_depth = 0 ;
138 m_ok = false ;
139 m_bitmapMask = NULL ;
140
141 #ifdef __WXMAC_OSX__
142 m_cgImageRef = NULL ;
143 #endif
144
145 m_iconRef = NULL ;
146 m_pictHandle = NULL ;
147 m_hBitmap = NULL ;
148 m_hMaskBitmap = NULL;
149 m_maskBytesPerRow = 0 ;
150
151 m_rawAccessCount = 0 ;
152 m_hasAlpha = false;
153 }
154
155 wxBitmapRefData::wxBitmapRefData()
156 {
157 Init() ;
158 }
159
160 wxBitmapRefData::wxBitmapRefData( int w , int h , int d )
161 {
162 Init() ;
163 Create( w , h , d ) ;
164 }
165
166 bool wxBitmapRefData::Create( int w , int h , int d )
167 {
168 m_width = wxMax(1, w);
169 m_height = wxMax(1, h);
170 m_depth = d ;
171
172 m_bytesPerRow = w * 4 ;
173 size_t size = m_bytesPerRow * h ;
174 void* data = m_memBuf.GetWriteBuf( size ) ;
175 memset( data , 0 , size ) ;
176 m_memBuf.UngetWriteBuf( size ) ;
177
178 m_hBitmap = NULL ;
179 Rect rect = { 0 , 0 , m_height , m_width } ;
180 verify_noerr( NewGWorldFromPtr( (GWorldPtr*) &m_hBitmap , k32ARGBPixelFormat , &rect , NULL , NULL , 0 ,
181 (char*) data , m_bytesPerRow ) ) ;
182 wxASSERT_MSG( m_hBitmap , wxT("Unable to create GWorld context") ) ;
183
184 m_ok = ( m_hBitmap != NULL ) ;
185
186 return m_ok ;
187 }
188
189 void wxBitmapRefData::UseAlpha( bool use )
190 {
191 if ( m_hasAlpha == use )
192 return ;
193
194 m_hasAlpha = use ;
195 if ( m_hasAlpha )
196 {
197 wxASSERT( m_hMaskBitmap == NULL ) ;
198
199 int width = GetWidth() ;
200 int height = GetHeight() ;
201 m_maskBytesPerRow = ( width * 4 + 3 ) & 0xFFFFFFC ;
202 size_t size = height * m_maskBytesPerRow ;
203 unsigned char * data = (unsigned char * ) m_maskMemBuf.GetWriteBuf( size ) ;
204 wxASSERT( data != NULL ) ;
205
206 memset( data , 0 , size ) ;
207 Rect rect = { 0 , 0 , height , width } ;
208 verify_noerr( NewGWorldFromPtr( (GWorldPtr*) &m_hMaskBitmap , k32ARGBPixelFormat , &rect , NULL , NULL , 0 ,
209 (char*) data , m_maskBytesPerRow ) ) ;
210 wxASSERT_MSG( m_hMaskBitmap , wxT("Unable to create GWorld context for alpha mask") ) ;
211 m_maskMemBuf.UngetWriteBuf(size) ;
212
213 #if !wxMAC_USE_CORE_GRAPHICS
214 UpdateAlphaMask() ;
215 #endif
216 }
217 else
218 {
219 DisposeGWorld( m_hMaskBitmap ) ;
220 m_hMaskBitmap = NULL ;
221 m_maskBytesPerRow = 0 ;
222 }
223 }
224
225 void *wxBitmapRefData::GetRawAccess() const
226 {
227 wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ;
228 return m_memBuf.GetData() ;
229 }
230
231 void *wxBitmapRefData::BeginRawAccess()
232 {
233 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") ) ;
234 wxASSERT( m_rawAccessCount == 0 ) ;
235 wxASSERT_MSG( m_pictHandle == NULL && m_iconRef == NULL ,
236 wxT("Currently, modifing bitmaps that are used in controls already is not supported") ) ;
237
238 ++m_rawAccessCount ;
239
240 #ifdef __WXMAC_OSX__
241 // we must destroy an existing cached image, as
242 // the bitmap data may change now
243 if ( m_cgImageRef )
244 {
245 CGImageRelease( m_cgImageRef ) ;
246 m_cgImageRef = NULL ;
247 }
248 #endif
249
250 return m_memBuf.GetData() ;
251 }
252
253 void wxBitmapRefData::EndRawAccess()
254 {
255 wxCHECK_RET( Ok() , wxT("invalid bitmap") ) ;
256 wxASSERT( m_rawAccessCount == 1 ) ;
257
258 --m_rawAccessCount ;
259
260 #if !wxMAC_USE_CORE_GRAPHICS
261 UpdateAlphaMask() ;
262 #endif
263 }
264
265 bool wxBitmapRefData::HasNativeSize()
266 {
267 int w = GetWidth() ;
268 int h = GetHeight() ;
269 int sz = wxMax( w , h ) ;
270
271 return ( sz == 128 || sz == 48 || sz == 32 || sz == 16 );
272 }
273
274 IconRef wxBitmapRefData::GetIconRef()
275 {
276 if ( m_iconRef == NULL )
277 {
278 // Create Icon Family Handle
279
280 IconFamilyHandle iconFamily = NULL ;
281
282 #ifdef WORDS_BIGENDIAN
283 iconFamily = (IconFamilyHandle) NewHandle( 8 ) ;
284 (**iconFamily).resourceType = kIconFamilyType ;
285 (**iconFamily).resourceSize = sizeof(OSType) + sizeof(Size);
286 #else
287 // test this solution on big endian as well
288 iconFamily = (IconFamilyHandle) NewHandle( 0 ) ;
289 #endif
290
291 int w = GetWidth() ;
292 int h = GetHeight() ;
293 int sz = wxMax( w , h ) ;
294
295 OSType dataType = 0 ;
296 OSType maskType = 0 ;
297
298 switch (sz)
299 {
300 case 128:
301 dataType = kThumbnail32BitData ;
302 maskType = kThumbnail8BitMask ;
303 break;
304
305 case 48:
306 dataType = kHuge32BitData ;
307 maskType = kHuge8BitMask ;
308 break;
309
310 case 32:
311 dataType = kLarge32BitData ;
312 maskType = kLarge8BitMask ;
313 break;
314
315 case 16:
316 dataType = kSmall32BitData ;
317 maskType = kSmall8BitMask ;
318 break;
319
320 default:
321 break;
322 }
323
324 if ( dataType != 0 )
325 {
326 // setup the header properly
327
328 Handle data = NULL ;
329 Handle maskdata = NULL ;
330 unsigned char * maskptr = NULL ;
331 unsigned char * ptr = NULL ;
332 size_t datasize, masksize ;
333
334 datasize = sz * sz * 4 ;
335 data = NewHandle( datasize ) ;
336 HLock( data ) ;
337 ptr = (unsigned char*) *data ;
338 memset( ptr , 0, datasize ) ;
339
340 masksize = sz * sz ;
341 maskdata = NewHandle( masksize ) ;
342 HLock( maskdata ) ;
343 maskptr = (unsigned char*) *maskdata ;
344 memset( maskptr , 0 , masksize ) ;
345
346 bool hasAlpha = HasAlpha() ;
347 wxMask *mask = m_bitmapMask ;
348 unsigned char * source = (unsigned char*) GetRawAccess() ;
349 unsigned char * masksource = mask ? (unsigned char*) mask->GetRawAccess() : NULL ;
350
351 for ( int y = 0 ; y < h ; ++y )
352 {
353 unsigned char * dest = ptr + y * sz * 4 ;
354 unsigned char * maskdest = maskptr + y * sz ;
355 unsigned char a, r, g, b;
356
357 for ( int x = 0 ; x < w ; ++x )
358 {
359 a = *source ++ ;
360 r = *source ++ ;
361 g = *source ++ ;
362 b = *source ++ ;
363
364 *dest++ = 0 ;
365 *dest++ = r ;
366 *dest++ = g ;
367 *dest++ = b ;
368
369 if ( mask )
370 {
371 *maskdest++ = 0xFF - *masksource++ ;
372 masksource++ ;
373 masksource++ ;
374 masksource++ ;
375 }
376 else if ( hasAlpha )
377 *maskdest++ = a ;
378 else
379 *maskdest++ = 0xFF ;
380 }
381 }
382
383 OSStatus err = SetIconFamilyData( iconFamily, dataType , data ) ;
384 wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;
385
386 err = SetIconFamilyData( iconFamily, maskType , maskdata ) ;
387 wxASSERT_MSG( err == noErr , wxT("Error when adding mask") ) ;
388
389 HUnlock( data ) ;
390 HUnlock( maskdata ) ;
391 DisposeHandle( data ) ;
392 DisposeHandle( maskdata ) ;
393 }
394 else
395 {
396 PicHandle pic = GetPictHandle() ;
397 SetIconFamilyData( iconFamily, 'PICT' , (Handle) pic ) ;
398 }
399 // transform into IconRef
400 #if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
401 // cleaner version existing from 10.3 upwards
402 HLock((Handle) iconFamily);
403 OSStatus err = GetIconRefFromIconFamilyPtr( *iconFamily, GetHandleSize((Handle) iconFamily), &m_iconRef );
404 HUnlock((Handle) iconFamily);
405 wxASSERT_MSG( err == noErr , wxT("Error when constructing icon ref") );
406 #else
407 static int iconCounter = 2 ;
408
409 OSStatus err = RegisterIconRefFromIconFamily( 'WXNG' , (OSType) iconCounter, iconFamily, &m_iconRef ) ;
410 wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;
411
412 // we have to retain a reference, as Unregister will decrement it
413 AcquireIconRef( m_iconRef ) ;
414 UnregisterIconRef( 'WXNG' , (OSType) iconCounter ) ;
415 ++iconCounter ;
416 #endif
417 DisposeHandle( (Handle) iconFamily ) ;
418 }
419
420 return m_iconRef ;
421 }
422
423 PicHandle wxBitmapRefData::GetPictHandle()
424 {
425 if ( m_pictHandle == NULL )
426 {
427 CGrafPtr origPort = NULL ;
428 GDHandle origDev = NULL ;
429 GWorldPtr wp = NULL ;
430 GWorldPtr mask = NULL ;
431 int height = GetHeight() ;
432 int width = GetWidth() ;
433
434 Rect rect = { 0 , 0 , height , width } ;
435 RgnHandle clipRgn = NULL ;
436
437 GetGWorld( &origPort , &origDev ) ;
438 wp = GetHBITMAP( &mask ) ;
439
440 if ( mask )
441 {
442 GWorldPtr monoworld ;
443 clipRgn = NewRgn() ;
444 OSStatus err = NewGWorld( &monoworld , 1 , &rect , NULL , NULL , 0 ) ;
445 verify_noerr(err) ;
446 LockPixels( GetGWorldPixMap( monoworld ) ) ;
447 LockPixels( GetGWorldPixMap( mask ) ) ;
448 SetGWorld( monoworld , NULL ) ;
449
450 RGBColor white = { 0xffff , 0xffff , 0xffff } ;
451 RGBColor black = { 0x0000 , 0x0000 , 0x0000 } ;
452 RGBForeColor( &black ) ;
453 RGBBackColor( &white ) ;
454
455 CopyBits(GetPortBitMapForCopyBits(mask),
456 GetPortBitMapForCopyBits(monoworld),
457 &rect,
458 &rect,
459 srcCopy, NULL);
460 BitMapToRegion( clipRgn , (BitMap*) *GetGWorldPixMap( monoworld ) ) ;
461
462 UnlockPixels( GetGWorldPixMap( monoworld ) ) ;
463 UnlockPixels( GetGWorldPixMap( mask ) ) ;
464 DisposeGWorld( monoworld ) ;
465 }
466
467 SetGWorld( wp , NULL ) ;
468 Rect portRect ;
469 GetPortBounds( wp , &portRect ) ;
470 m_pictHandle = OpenPicture(&portRect);
471
472 if (m_pictHandle)
473 {
474 RGBColor white = { 0xffff , 0xffff , 0xffff } ;
475 RGBColor black = { 0x0000 , 0x0000 , 0x0000 } ;
476
477 RGBForeColor( &black ) ;
478 RGBBackColor( &white ) ;
479
480 if ( clipRgn )
481 SetClip( clipRgn ) ;
482
483 LockPixels( GetGWorldPixMap( wp ) ) ;
484 CopyBits(GetPortBitMapForCopyBits(wp),
485 GetPortBitMapForCopyBits(wp),
486 &portRect,
487 &portRect,
488 srcCopy,clipRgn);
489 UnlockPixels( GetGWorldPixMap( wp ) ) ;
490 ClosePicture();
491 }
492
493 SetGWorld( origPort , origDev ) ;
494 if ( clipRgn )
495 DisposeRgn( clipRgn ) ;
496 }
497
498 return m_pictHandle ;
499 }
500
501 #ifdef __WXMAC_OSX__
502 void wxMacMemoryBufferReleaseProc(void *info, const void *data, size_t size)
503 {
504 wxMemoryBuffer* membuf = (wxMemoryBuffer*) info ;
505
506 wxASSERT( data == membuf->GetData() ) ;
507
508 delete membuf ;
509 }
510
511 CGImageRef wxBitmapRefData::CGImageCreate() const
512 {
513 wxASSERT( m_ok ) ;
514 wxASSERT( m_rawAccessCount >= 0 ) ;
515 CGImageRef image ;
516 if ( m_rawAccessCount > 0 || m_cgImageRef == NULL )
517 {
518 size_t imageSize = m_width * m_height * 4 ;
519 void * dataBuffer = m_memBuf.GetData() ;
520 int w = m_width ;
521 int h = m_height ;
522 CGImageAlphaInfo alphaInfo = kCGImageAlphaNoneSkipFirst ;
523 wxMemoryBuffer* membuf = NULL ;
524
525 if ( m_bitmapMask )
526 {
527 alphaInfo = kCGImageAlphaFirst ;
528 membuf = new wxMemoryBuffer( imageSize ) ;
529 memcpy( membuf->GetData() , dataBuffer , imageSize ) ;
530 unsigned char *sourcemaskstart = (unsigned char *) m_bitmapMask->GetRawAccess() ;
531 int maskrowbytes = m_bitmapMask->GetBytesPerRow() ;
532 unsigned char *destalpha = (unsigned char *) membuf->GetData() ;
533 for ( int y = 0 ; y < h ; ++y , sourcemaskstart += maskrowbytes)
534 {
535 unsigned char *sourcemask = sourcemaskstart ;
536 for ( int x = 0 ; x < w ; ++x , sourcemask += 4 , destalpha += 4 )
537 {
538 *destalpha = 0xFF - *sourcemask ;
539 }
540 }
541 }
542 else
543 {
544 if ( m_hasAlpha )
545 {
546 #if wxMAC_USE_PREMULTIPLIED_ALPHA
547 alphaInfo = kCGImageAlphaPremultipliedFirst ;
548 #else
549 alphaInfo = kCGImageAlphaFirst ;
550 #endif
551 }
552
553 membuf = new wxMemoryBuffer( m_memBuf ) ;
554 }
555
556 CGColorSpaceRef colorSpace = wxMacGetGenericRGBColorSpace();
557 CGDataProviderRef dataProvider =
558 CGDataProviderCreateWithData(
559 membuf , (const void *)membuf->GetData() , imageSize,
560 wxMacMemoryBufferReleaseProc );
561 image =
562 ::CGImageCreate(
563 w, h, 8 , 32 , 4 * m_width , colorSpace, alphaInfo ,
564 dataProvider, NULL , false , kCGRenderingIntentDefault );
565 CGDataProviderRelease( dataProvider);
566 }
567 else
568 {
569 image = m_cgImageRef ;
570 CGImageRetain( image ) ;
571 }
572
573 if ( m_rawAccessCount == 0 && m_cgImageRef == NULL)
574 {
575 // we keep it for later use
576 m_cgImageRef = image ;
577 CGImageRetain( image ) ;
578 }
579
580 return image ;
581 }
582 #endif
583
584 GWorldPtr wxBitmapRefData::GetHBITMAP(GWorldPtr* mask) const
585 {
586 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
587 if ( mask )
588 {
589 *mask = NULL ;
590 if ( m_bitmapMask )
591 {
592 *mask = (GWorldPtr) m_bitmapMask->GetHBITMAP() ;
593 }
594 else if ( m_hasAlpha )
595 {
596 #if !wxMAC_USE_CORE_GRAPHICS
597 if ( m_rawAccessCount > 0 )
598 UpdateAlphaMask() ;
599 #else
600 // this structure is not kept in synch when using CG, so if something
601 // is really accessing the GrafPorts, we have to sync it
602 UpdateAlphaMask() ;
603 #endif
604
605 *mask = m_hMaskBitmap ;
606 }
607 }
608
609 return m_hBitmap ;
610 }
611
612 void wxBitmapRefData::UpdateAlphaMask() const
613 {
614 if ( m_hasAlpha )
615 {
616 unsigned char *sourcemask = (unsigned char *) GetRawAccess() ;
617 unsigned char *destalphabase = (unsigned char *) m_maskMemBuf.GetData() ;
618
619 int h = GetHeight() ;
620 int w = GetWidth() ;
621
622 for ( int y = 0 ; y < h ; ++y , destalphabase += m_maskBytesPerRow )
623 {
624 unsigned char* destalpha = destalphabase ;
625
626 for ( int x = 0 ; x < w ; ++x , sourcemask += 4 )
627 {
628 // we must have 24 bit depth for non quartz smooth alpha
629 *destalpha++ = 255 ;
630 *destalpha++ = 255 - *sourcemask ;
631 *destalpha++ = 255 - *sourcemask ;
632 *destalpha++ = 255 - *sourcemask ;
633 }
634 }
635 }
636 }
637
638 void wxBitmapRefData::Free()
639 {
640 wxASSERT_MSG( m_rawAccessCount == 0 , wxT("Bitmap still selected when destroyed") ) ;
641
642 #ifdef __WXMAC_OSX__
643 if ( m_cgImageRef )
644 {
645 CGImageRelease( m_cgImageRef ) ;
646 m_cgImageRef = NULL ;
647 }
648 #endif
649
650 if ( m_iconRef )
651 {
652 ReleaseIconRef( m_iconRef ) ;
653 m_iconRef = NULL ;
654 }
655
656 if ( m_pictHandle )
657 {
658 KillPicture( m_pictHandle ) ;
659 m_pictHandle = NULL ;
660 }
661
662 if ( m_hBitmap )
663 {
664 DisposeGWorld( MAC_WXHBITMAP(m_hBitmap) ) ;
665 m_hBitmap = NULL ;
666 }
667
668 if ( m_hMaskBitmap )
669 {
670 DisposeGWorld( MAC_WXHBITMAP(m_hMaskBitmap) ) ;
671 m_hMaskBitmap = NULL ;
672 }
673
674 if (m_bitmapMask)
675 {
676 delete m_bitmapMask;
677 m_bitmapMask = NULL;
678 }
679 }
680
681 wxBitmapRefData::~wxBitmapRefData()
682 {
683 Free() ;
684 }
685
686 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
687 {
688 bool created = false ;
689 int w = icon.GetWidth() ;
690 int h = icon.GetHeight() ;
691
692 Create( icon.GetWidth() , icon.GetHeight() ) ;
693
694 if ( w == h && ( w == 16 || w == 32 || w == 48 || w == 128 ) )
695 {
696 IconFamilyHandle iconFamily = NULL ;
697 Handle imagehandle = NewHandle( 0 ) ;
698 Handle maskhandle = NewHandle( 0 ) ;
699
700 OSType maskType = 0;
701 OSType dataType = 0;
702 IconSelectorValue selector = 0 ;
703
704 switch (w)
705 {
706 case 128:
707 dataType = kThumbnail32BitData ;
708 maskType = kThumbnail8BitMask ;
709 selector = kSelectorAllAvailableData ;
710 break;
711
712 case 48:
713 dataType = kHuge32BitData ;
714 maskType = kHuge8BitMask ;
715 selector = kSelectorHuge32Bit | kSelectorHuge8BitMask ;
716 break;
717
718 case 32:
719 dataType = kLarge32BitData ;
720 maskType = kLarge8BitMask ;
721 selector = kSelectorLarge32Bit | kSelectorLarge8BitMask ;
722 break;
723
724 case 16:
725 dataType = kSmall32BitData ;
726 maskType = kSmall8BitMask ;
727 selector = kSelectorSmall32Bit | kSelectorSmall8BitMask ;
728 break;
729
730 default:
731 break;
732 }
733
734 OSStatus err = IconRefToIconFamily( MAC_WXHICON(icon.GetHICON()) , selector , &iconFamily ) ;
735
736 err = GetIconFamilyData( iconFamily , dataType , imagehandle ) ;
737 err = GetIconFamilyData( iconFamily , maskType , maskhandle ) ;
738 size_t imagehandlesize = GetHandleSize( imagehandle ) ;
739 size_t maskhandlesize = GetHandleSize( maskhandle ) ;
740
741 if ( imagehandlesize != 0 && maskhandlesize != 0 )
742 {
743 wxASSERT( GetHandleSize( imagehandle ) == w * 4 * h ) ;
744 wxASSERT( GetHandleSize( maskhandle ) == w * h ) ;
745
746 UseAlpha() ;
747
748 unsigned char *source = (unsigned char *) *imagehandle ;
749 unsigned char *sourcemask = (unsigned char *) *maskhandle ;
750 unsigned char* destination = (unsigned char*) BeginRawAccess() ;
751
752 for ( int y = 0 ; y < h ; ++y )
753 {
754 for ( int x = 0 ; x < w ; ++x )
755 {
756 *destination++ = *sourcemask++ ;
757 source++ ;
758 *destination++ = *source++ ;
759 *destination++ = *source++ ;
760 *destination++ = *source++ ;
761 }
762 }
763
764 EndRawAccess() ;
765 DisposeHandle( imagehandle ) ;
766 DisposeHandle( maskhandle ) ;
767 created = true ;
768 }
769
770 DisposeHandle( (Handle) iconFamily ) ;
771 }
772
773 if ( !created )
774 {
775 wxMemoryDC dc ;
776 dc.SelectObject( *this ) ;
777 dc.DrawIcon( icon , 0 , 0 ) ;
778 dc.SelectObject( wxNullBitmap ) ;
779 }
780
781 return true;
782 }
783
784 wxBitmap::wxBitmap()
785 {
786 }
787
788 wxBitmap::~wxBitmap()
789 {
790 }
791
792 wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
793 {
794 m_refData = new wxBitmapRefData( the_width , the_height , no_bits ) ;
795
796 if ( no_bits == 1 )
797 {
798 int linesize = ( the_width / (sizeof(unsigned char) * 8)) ;
799 if ( the_width % (sizeof(unsigned char) * 8) )
800 linesize += sizeof(unsigned char);
801
802 unsigned char* linestart = (unsigned char*) bits ;
803 unsigned char* destination = (unsigned char*) BeginRawAccess() ;
804
805 for ( int y = 0 ; y < the_height ; ++y , linestart += linesize )
806 {
807 int index, bit, mask;
808
809 for ( int x = 0 ; x < the_width ; ++x )
810 {
811 index = x / 8 ;
812 bit = x % 8 ;
813 mask = 1 << bit ;
814
815 if ( !(linestart[index] & mask ) )
816 {
817 *destination++ = 0xFF ;
818 *destination++ = 0 ;
819 *destination++ = 0 ;
820 *destination++ = 0 ;
821 }
822 else
823 {
824 *destination++ = 0xFF ;
825 *destination++ = 0xFF ;
826 *destination++ = 0xFF ;
827 *destination++ = 0xFF ;
828 }
829 }
830 }
831
832 EndRawAccess() ;
833 }
834 else
835 {
836 wxFAIL_MSG(wxT("multicolor BITMAPs not yet implemented"));
837 }
838 }
839
840 wxBitmap::wxBitmap(int w, int h, int d)
841 {
842 (void)Create(w, h, d);
843 }
844
845 wxBitmap::wxBitmap(void *data, wxBitmapType type, int width, int height, int depth)
846 {
847 (void) Create(data, type, width, height, depth);
848 }
849
850 wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
851 {
852 LoadFile(filename, type);
853 }
854
855 wxBitmap::wxBitmap(const char **bits)
856 {
857 (void) CreateFromXpm(bits);
858 }
859
860 wxBitmap::wxBitmap(char **bits)
861 {
862 (void) CreateFromXpm((const char **)bits);
863 }
864
865 void * wxBitmap::GetRawAccess() const
866 {
867 wxCHECK_MSG( Ok() , NULL , wxT("invalid bitmap") ) ;
868
869 return M_BITMAPDATA->GetRawAccess() ;
870 }
871
872 void * wxBitmap::BeginRawAccess()
873 {
874 wxCHECK_MSG( Ok() , NULL , wxT("invalid bitmap") ) ;
875
876 return M_BITMAPDATA->BeginRawAccess() ;
877 }
878
879 void wxBitmap::EndRawAccess()
880 {
881 wxCHECK_RET( Ok() , wxT("invalid bitmap") ) ;
882
883 M_BITMAPDATA->EndRawAccess() ;
884 }
885
886 bool wxBitmap::CreateFromXpm(const char **bits)
887 {
888 #if wxUSE_IMAGE
889 wxCHECK_MSG( bits != NULL, false, wxT("invalid bitmap data") );
890
891 wxXPMDecoder decoder;
892 wxImage img = decoder.ReadData(bits);
893 wxCHECK_MSG( img.Ok(), false, wxT("invalid bitmap data") );
894
895 *this = wxBitmap(img);
896
897 return true;
898 #else
899
900 return false;
901 #endif
902 }
903
904 #ifdef __WXMAC_OSX__
905 WXCGIMAGEREF wxBitmap::CGImageCreate() const
906 {
907 wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ;
908
909 return M_BITMAPDATA->CGImageCreate() ;
910 }
911 #endif
912
913 wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const
914 {
915 wxCHECK_MSG( Ok() &&
916 (rect.x >= 0) && (rect.y >= 0) &&
917 (rect.x+rect.width <= GetWidth()) &&
918 (rect.y+rect.height <= GetHeight()),
919 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
920
921 wxBitmap ret( rect.width, rect.height, GetDepth() );
922 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
923
924 int sourcewidth = GetWidth() ;
925 int destwidth = rect.width ;
926 int destheight = rect.height ;
927
928 {
929 unsigned char *sourcedata = (unsigned char*) GetRawAccess() ;
930 unsigned char *destdata = (unsigned char*) ret.BeginRawAccess() ;
931 wxASSERT( (sourcedata != NULL) && (destdata != NULL) ) ;
932
933 int sourcelinesize = sourcewidth * 4 ;
934 int destlinesize = destwidth * 4 ;
935 unsigned char *source = sourcedata + rect.x * 4 + rect.y * sourcelinesize ;
936 unsigned char *dest = destdata ;
937
938 for (int yy = 0; yy < destheight; ++yy, source += sourcelinesize , dest += destlinesize)
939 {
940 memcpy( dest , source , destlinesize ) ;
941 }
942 }
943
944 ret.EndRawAccess() ;
945
946 if ( M_BITMAPDATA->m_bitmapMask )
947 {
948 wxMemoryBuffer maskbuf ;
949 int rowBytes = ( destwidth * 4 + 3 ) & 0xFFFFFFC ;
950 size_t maskbufsize = rowBytes * destheight ;
951
952 int sourcelinesize = M_BITMAPDATA->m_bitmapMask->GetBytesPerRow() ;
953 int destlinesize = rowBytes ;
954
955 unsigned char *source = (unsigned char *) M_BITMAPDATA->m_bitmapMask->GetRawAccess() ;
956 unsigned char *destdata = (unsigned char * ) maskbuf.GetWriteBuf( maskbufsize ) ;
957 wxASSERT( (source != NULL) && (destdata != NULL) ) ;
958
959 source += rect.x * 4 + rect.y * sourcelinesize ;
960 unsigned char *dest = destdata ;
961
962 for (int yy = 0; yy < destheight; ++yy, source += sourcelinesize , dest += destlinesize)
963 {
964 memcpy( dest , source , destlinesize ) ;
965 }
966
967 maskbuf.UngetWriteBuf( maskbufsize ) ;
968 ret.SetMask( new wxMask( maskbuf , destwidth , destheight , rowBytes ) ) ;
969 }
970 else if ( HasAlpha() )
971 ret.UseAlpha() ;
972
973 return ret;
974 }
975
976 bool wxBitmap::Create(int w, int h, int d)
977 {
978 UnRef();
979
980 if ( d < 0 )
981 d = wxDisplayDepth() ;
982
983 m_refData = new wxBitmapRefData( w , h , d );
984
985 return M_BITMAPDATA->Ok() ;
986 }
987
988 bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
989 {
990 UnRef();
991
992 wxBitmapHandler *handler = FindHandler(type);
993
994 if ( handler )
995 {
996 m_refData = new wxBitmapRefData;
997
998 return handler->LoadFile(this, filename, type, -1, -1);
999 }
1000 else
1001 {
1002 #if wxUSE_IMAGE
1003 wxImage loadimage(filename, type);
1004 if (loadimage.Ok())
1005 {
1006 *this = loadimage;
1007
1008 return true;
1009 }
1010 #endif
1011 }
1012
1013 wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
1014
1015 return false;
1016 }
1017
1018 bool wxBitmap::Create(void *data, wxBitmapType type, int width, int height, int depth)
1019 {
1020 UnRef();
1021
1022 m_refData = new wxBitmapRefData;
1023
1024 wxBitmapHandler *handler = FindHandler(type);
1025
1026 if ( handler == NULL )
1027 {
1028 wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
1029
1030 return false;
1031 }
1032
1033 return handler->Create(this, data, type, width, height, depth);
1034 }
1035
1036 #if wxUSE_IMAGE
1037
1038 wxBitmap::wxBitmap(const wxImage& image, int depth)
1039 {
1040 wxCHECK_RET( image.Ok(), wxT("invalid image") );
1041
1042 // width and height of the device-dependent bitmap
1043 int width = image.GetWidth();
1044 int height = image.GetHeight();
1045
1046 m_refData = new wxBitmapRefData( width , height , depth ) ;
1047
1048 // Create picture
1049
1050 bool hasAlpha = false ;
1051
1052 if ( image.HasMask() )
1053 {
1054 // takes precedence, don't mix with alpha info
1055 }
1056 else
1057 {
1058 hasAlpha = image.HasAlpha() ;
1059 }
1060
1061 if ( hasAlpha )
1062 UseAlpha() ;
1063
1064 unsigned char* destination = (unsigned char*) BeginRawAccess() ;
1065 register unsigned char* data = image.GetData();
1066 const unsigned char *alpha = hasAlpha ? image.GetAlpha() : NULL ;
1067
1068 for (int y = 0; y < height; y++)
1069 {
1070 for (int x = 0; x < width; x++)
1071 {
1072 if ( hasAlpha )
1073 {
1074 const unsigned char a = *alpha++;
1075 *destination++ = a ;
1076
1077 #if wxMAC_USE_PREMULTIPLIED_ALPHA
1078 *destination++ = ((*data++) * a + 127) / 255 ;
1079 *destination++ = ((*data++) * a + 127) / 255 ;
1080 *destination++ = ((*data++) * a + 127) / 255 ;
1081 #else
1082 *destination++ = *data++ ;
1083 *destination++ = *data++ ;
1084 *destination++ = *data++ ;
1085 #endif
1086 }
1087 else
1088 {
1089 *destination++ = 0xFF ;
1090 *destination++ = *data++ ;
1091 *destination++ = *data++ ;
1092 *destination++ = *data++ ;
1093 }
1094 }
1095 }
1096
1097 EndRawAccess() ;
1098 if ( image.HasMask() )
1099 SetMask( new wxMask( *this , wxColour( image.GetMaskRed() , image.GetMaskGreen() , image.GetMaskBlue() ) ) ) ;
1100 }
1101
1102 wxImage wxBitmap::ConvertToImage() const
1103 {
1104 wxImage image;
1105
1106 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
1107
1108 // create an wxImage object
1109 int width = GetWidth();
1110 int height = GetHeight();
1111 image.Create( width, height );
1112
1113 unsigned char *data = image.GetData();
1114 wxCHECK_MSG( data, wxNullImage, wxT("Could not allocate data for image") );
1115
1116 unsigned char* source = (unsigned char*) GetRawAccess() ;
1117
1118 bool hasAlpha = false ;
1119 bool hasMask = false ;
1120 int maskBytesPerRow = 0 ;
1121 unsigned char *alpha = NULL ;
1122 unsigned char *mask = NULL ;
1123
1124 if ( HasAlpha() )
1125 hasAlpha = true ;
1126
1127 if ( GetMask() )
1128 {
1129 hasMask = true ;
1130 mask = (unsigned char*) GetMask()->GetRawAccess() ;
1131 maskBytesPerRow = GetMask()->GetBytesPerRow() ;
1132 }
1133
1134 if ( hasAlpha )
1135 {
1136 image.SetAlpha() ;
1137 alpha = image.GetAlpha() ;
1138 }
1139
1140 int index = 0;
1141
1142 // The following masking algorithm is the same as well in msw/gtk:
1143 // the colour used as transparent one in wxImage and the one it is
1144 // replaced with when it actually occurs in the bitmap
1145 static const int MASK_RED = 1;
1146 static const int MASK_GREEN = 2;
1147 static const int MASK_BLUE = 3;
1148 static const int MASK_BLUE_REPLACEMENT = 2;
1149
1150 for (int yy = 0; yy < height; yy++ , mask += maskBytesPerRow )
1151 {
1152 unsigned char * maskp = mask ;
1153 unsigned char a, r, g, b;
1154 long color;
1155
1156 for (int xx = 0; xx < width; xx++)
1157 {
1158 color = *((long*) source) ;
1159 #ifdef WORDS_BIGENDIAN
1160 a = ((color&0xFF000000) >> 24) ;
1161 r = ((color&0x00FF0000) >> 16) ;
1162 g = ((color&0x0000FF00) >> 8) ;
1163 b = (color&0x000000FF);
1164 #else
1165 b = ((color&0xFF000000) >> 24) ;
1166 g = ((color&0x00FF0000) >> 16) ;
1167 r = ((color&0x0000FF00) >> 8) ;
1168 a = (color&0x000000FF);
1169 #endif
1170 if ( hasMask )
1171 {
1172 if ( *maskp++ == 0xFF )
1173 {
1174 r = MASK_RED ;
1175 g = MASK_GREEN ;
1176 b = MASK_BLUE ;
1177 }
1178 else if ( r == MASK_RED && g == MASK_GREEN && b == MASK_BLUE )
1179 b = MASK_BLUE_REPLACEMENT ;
1180
1181 maskp++ ;
1182 maskp++ ;
1183 maskp++ ;
1184 }
1185 else if ( hasAlpha )
1186 *alpha++ = a ;
1187
1188 data[index ] = r ;
1189 data[index + 1] = g ;
1190 data[index + 2] = b ;
1191
1192 index += 3;
1193 source += 4 ;
1194 }
1195 }
1196
1197 if ( hasMask )
1198 image.SetMaskColour( MASK_RED, MASK_GREEN, MASK_BLUE );
1199
1200 return image;
1201 }
1202
1203 #endif //wxUSE_IMAGE
1204
1205 bool wxBitmap::SaveFile( const wxString& filename,
1206 wxBitmapType type, const wxPalette *palette ) const
1207 {
1208 bool success = false;
1209 wxBitmapHandler *handler = FindHandler(type);
1210
1211 if ( handler )
1212 {
1213 success = handler->SaveFile(this, filename, type, palette);
1214 }
1215 else
1216 {
1217 #if wxUSE_IMAGE
1218 wxImage image = ConvertToImage();
1219 success = image.SaveFile(filename, type);
1220 #else
1221 wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
1222 #endif
1223 }
1224
1225 return success;
1226 }
1227
1228 bool wxBitmap::Ok() const
1229 {
1230 return (M_BITMAPDATA && M_BITMAPDATA->Ok());
1231 }
1232
1233 int wxBitmap::GetHeight() const
1234 {
1235 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1236
1237 return M_BITMAPDATA->GetHeight();
1238 }
1239
1240 int wxBitmap::GetWidth() const
1241 {
1242 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1243
1244 return M_BITMAPDATA->GetWidth() ;
1245 }
1246
1247 int wxBitmap::GetDepth() const
1248 {
1249 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1250
1251 return M_BITMAPDATA->GetDepth();
1252 }
1253
1254 #if WXWIN_COMPATIBILITY_2_4
1255 int wxBitmap::GetQuality() const
1256 {
1257 return 0;
1258 }
1259
1260 void wxBitmap::SetQuality(int WXUNUSED(quality))
1261 {
1262 }
1263 #endif
1264
1265 wxMask *wxBitmap::GetMask() const
1266 {
1267 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
1268
1269 return M_BITMAPDATA->m_bitmapMask;
1270 }
1271
1272 bool wxBitmap::HasAlpha() const
1273 {
1274 wxCHECK_MSG( Ok(), false , wxT("invalid bitmap") );
1275
1276 return M_BITMAPDATA->HasAlpha() ;
1277 }
1278
1279 void wxBitmap::SetWidth(int w)
1280 {
1281 if (!M_BITMAPDATA)
1282 m_refData = new wxBitmapRefData;
1283
1284 M_BITMAPDATA->SetWidth(w);
1285 }
1286
1287 void wxBitmap::SetHeight(int h)
1288 {
1289 if (!M_BITMAPDATA)
1290 m_refData = new wxBitmapRefData;
1291
1292 M_BITMAPDATA->SetHeight(h);
1293 }
1294
1295 void wxBitmap::SetDepth(int d)
1296 {
1297 if (!M_BITMAPDATA)
1298 m_refData = new wxBitmapRefData;
1299
1300 M_BITMAPDATA->SetDepth(d);
1301 }
1302
1303 void wxBitmap::SetOk(bool isOk)
1304 {
1305 if (!M_BITMAPDATA)
1306 m_refData = new wxBitmapRefData;
1307
1308 M_BITMAPDATA->SetOk(isOk);
1309 }
1310
1311 #if wxUSE_PALETTE
1312 wxPalette *wxBitmap::GetPalette() const
1313 {
1314 wxCHECK_MSG( Ok(), NULL, wxT("Invalid bitmap GetPalette()") );
1315
1316 return &M_BITMAPDATA->m_bitmapPalette;
1317 }
1318
1319 void wxBitmap::SetPalette(const wxPalette& palette)
1320 {
1321 if (!M_BITMAPDATA)
1322 m_refData = new wxBitmapRefData;
1323
1324 M_BITMAPDATA->m_bitmapPalette = palette ;
1325 }
1326 #endif // wxUSE_PALETTE
1327
1328 void wxBitmap::SetMask(wxMask *mask)
1329 {
1330 if (!M_BITMAPDATA)
1331 m_refData = new wxBitmapRefData;
1332
1333 // Remove existing mask if there is one.
1334 delete M_BITMAPDATA->m_bitmapMask;
1335
1336 M_BITMAPDATA->m_bitmapMask = mask ;
1337 }
1338
1339 WXHBITMAP wxBitmap::GetHBITMAP(WXHBITMAP* mask) const
1340 {
1341 return WXHBITMAP(M_BITMAPDATA->GetHBITMAP((GWorldPtr*)mask));
1342 }
1343
1344 // ----------------------------------------------------------------------------
1345 // wxMask
1346 // ----------------------------------------------------------------------------
1347
1348 wxMask::wxMask()
1349 {
1350 Init() ;
1351 }
1352
1353 // Construct a mask from a bitmap and a colour indicating
1354 // the transparent area
1355 wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
1356 {
1357 Init() ;
1358 Create( bitmap, colour );
1359 }
1360
1361 // Construct a mask from a mono bitmap (copies the bitmap).
1362 wxMask::wxMask( const wxBitmap& bitmap )
1363 {
1364 Init() ;
1365 Create( bitmap );
1366 }
1367
1368 // Construct a mask from a mono bitmap (copies the bitmap).
1369
1370 wxMask::wxMask( const wxMemoryBuffer& data, int width , int height , int bytesPerRow )
1371 {
1372 Init() ;
1373 Create( data, width , height , bytesPerRow );
1374 }
1375
1376 wxMask::~wxMask()
1377 {
1378 if ( m_maskBitmap )
1379 {
1380 DisposeGWorld( (GWorldPtr)m_maskBitmap ) ;
1381 m_maskBitmap = NULL ;
1382 }
1383 }
1384
1385 void wxMask::Init()
1386 {
1387 m_width = m_height = m_bytesPerRow = 0 ;
1388 m_maskBitmap = NULL ;
1389 }
1390
1391 void *wxMask::GetRawAccess() const
1392 {
1393 return m_memBuf.GetData() ;
1394 }
1395
1396 // The default ColorTable for k8IndexedGrayPixelFormat in Intel appears to be broken, so we'll use an non-indexed
1397 // bitmap mask instead; in order to keep the code simple, the change applies to PowerPC implementations as well
1398
1399 void wxMask::RealizeNative()
1400 {
1401 if ( m_maskBitmap )
1402 {
1403 DisposeGWorld( (GWorldPtr)m_maskBitmap ) ;
1404 m_maskBitmap = NULL ;
1405 }
1406
1407 Rect rect = { 0 , 0 , m_height , m_width } ;
1408
1409 OSStatus err = NewGWorldFromPtr(
1410 (GWorldPtr*) &m_maskBitmap , k32ARGBPixelFormat , &rect , NULL , NULL , 0 ,
1411 (char*) m_memBuf.GetData() , m_bytesPerRow ) ;
1412 verify_noerr( err ) ;
1413 }
1414
1415 // Create a mask from a mono bitmap (copies the bitmap).
1416
1417 bool wxMask::Create(const wxMemoryBuffer& data,int width , int height , int bytesPerRow)
1418 {
1419 m_memBuf = data ;
1420 m_width = width ;
1421 m_height = height ;
1422 m_bytesPerRow = bytesPerRow ;
1423
1424 wxASSERT( data.GetDataLen() == (size_t)(height * bytesPerRow) ) ;
1425
1426 RealizeNative() ;
1427
1428 return true ;
1429 }
1430
1431 // Create a mask from a mono bitmap (copies the bitmap).
1432 bool wxMask::Create(const wxBitmap& bitmap)
1433 {
1434 m_width = bitmap.GetWidth() ;
1435 m_height = bitmap.GetHeight() ;
1436 m_bytesPerRow = ( m_width * 4 + 3 ) & 0xFFFFFFC ;
1437
1438 size_t size = m_bytesPerRow * m_height ;
1439 unsigned char * destdatabase = (unsigned char*) m_memBuf.GetWriteBuf( size ) ;
1440 wxASSERT( destdatabase != NULL ) ;
1441
1442 memset( destdatabase , 0 , size ) ;
1443 unsigned char * srcdata = (unsigned char*) bitmap.GetRawAccess() ;
1444
1445 for ( int y = 0 ; y < m_height ; ++y , destdatabase += m_bytesPerRow )
1446 {
1447 unsigned char *destdata = destdatabase ;
1448 unsigned char r, g, b;
1449
1450 for ( int x = 0 ; x < m_width ; ++x )
1451 {
1452 srcdata++ ;
1453 r = *srcdata++ ;
1454 g = *srcdata++ ;
1455 b = *srcdata++ ;
1456
1457 if ( ( r + g + b ) > 0x10 )
1458 {
1459 *destdata++ = 0xFF ;
1460 *destdata++ = 0xFF ;
1461 *destdata++ = 0xFF ;
1462 *destdata++ = 0xFF ;
1463 }
1464 else
1465 {
1466 *destdata++ = 0x00 ;
1467 *destdata++ = 0x00 ;
1468 *destdata++ = 0x00 ;
1469 *destdata++ = 0x00 ;
1470 }
1471 }
1472 }
1473
1474 m_memBuf.UngetWriteBuf( size ) ;
1475 RealizeNative() ;
1476
1477 return true;
1478 }
1479
1480 // Create a mask from a bitmap and a colour indicating
1481 // the transparent area
1482 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
1483 {
1484 m_width = bitmap.GetWidth() ;
1485 m_height = bitmap.GetHeight() ;
1486 m_bytesPerRow = ( m_width * 4 + 3 ) & 0xFFFFFFC ;
1487
1488 size_t size = m_bytesPerRow * m_height ;
1489 unsigned char * destdatabase = (unsigned char*) m_memBuf.GetWriteBuf( size ) ;
1490 wxASSERT( destdatabase != NULL ) ;
1491
1492 memset( destdatabase , 0 , size ) ;
1493 unsigned char * srcdata = (unsigned char*) bitmap.GetRawAccess() ;
1494
1495 for ( int y = 0 ; y < m_height ; ++y , destdatabase += m_bytesPerRow)
1496 {
1497 unsigned char *destdata = destdatabase ;
1498 unsigned char r, g, b;
1499
1500 for ( int x = 0 ; x < m_width ; ++x )
1501 {
1502 srcdata++ ;
1503 r = *srcdata++ ;
1504 g = *srcdata++ ;
1505 b = *srcdata++ ;
1506
1507 if ( colour == wxColour( r , g , b ) )
1508 {
1509 *destdata++ = 0xFF ;
1510 *destdata++ = 0xFF ;
1511 *destdata++ = 0xFF ;
1512 *destdata++ = 0xFF ;
1513 }
1514 else
1515 {
1516 *destdata++ = 0x00 ;
1517 *destdata++ = 0x00 ;
1518 *destdata++ = 0x00 ;
1519 *destdata++ = 0x00 ;
1520 }
1521 }
1522 }
1523
1524 m_memBuf.UngetWriteBuf( size ) ;
1525 RealizeNative() ;
1526
1527 return true;
1528 }
1529
1530 WXHBITMAP wxMask::GetHBITMAP() const
1531 {
1532 return m_maskBitmap ;
1533 }
1534
1535 // ----------------------------------------------------------------------------
1536 // wxBitmapHandler
1537 // ----------------------------------------------------------------------------
1538
1539 wxBitmapHandler::~wxBitmapHandler()
1540 {
1541 }
1542
1543 bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth)
1544 {
1545 return false;
1546 }
1547
1548 bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1549 int desiredWidth, int desiredHeight)
1550 {
1551 return false;
1552 }
1553
1554 bool wxBitmapHandler::SaveFile(const wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
1555 {
1556 return false;
1557 }
1558
1559 // ----------------------------------------------------------------------------
1560 // Standard Handlers
1561 // ----------------------------------------------------------------------------
1562
1563 class WXDLLEXPORT wxPICTResourceHandler: public wxBitmapHandler
1564 {
1565 DECLARE_DYNAMIC_CLASS(wxPICTResourceHandler)
1566
1567 public:
1568 inline wxPICTResourceHandler()
1569 {
1570 SetName(wxT("Macintosh Pict resource"));
1571 SetExtension(wxEmptyString);
1572 SetType(wxBITMAP_TYPE_PICT_RESOURCE);
1573 };
1574
1575 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1576 int desiredWidth, int desiredHeight);
1577 };
1578
1579 IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler)
1580
1581
1582 bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1583 int desiredWidth, int desiredHeight)
1584 {
1585 #if wxUSE_METAFILE
1586 Str255 theName ;
1587 wxMacStringToPascal( name , theName ) ;
1588
1589 PicHandle thePict = (PicHandle ) GetNamedResource( 'PICT' , theName ) ;
1590 if ( thePict )
1591 {
1592 wxMetafile mf ;
1593
1594 mf.SetHMETAFILE( (WXHMETAFILE) thePict ) ;
1595 bitmap->Create( mf.GetWidth() , mf.GetHeight() ) ;
1596 wxMemoryDC dc ;
1597 dc.SelectObject( *bitmap ) ;
1598 mf.Play( &dc ) ;
1599 dc.SelectObject( wxNullBitmap ) ;
1600
1601 return true ;
1602 }
1603 #endif
1604
1605 return false ;
1606 }
1607
1608 void wxBitmap::InitStandardHandlers()
1609 {
1610 AddHandler( new wxPICTResourceHandler ) ;
1611 AddHandler( new wxICONResourceHandler ) ;
1612 }
1613
1614 // ----------------------------------------------------------------------------
1615 // raw bitmap access support
1616 // ----------------------------------------------------------------------------
1617
1618 void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
1619 {
1620 if ( !Ok() )
1621 // no bitmap, no data (raw or otherwise)
1622 return NULL;
1623
1624 data.m_width = GetWidth() ;
1625 data.m_height = GetHeight() ;
1626 data.m_stride = GetWidth() * 4 ;
1627
1628 return BeginRawAccess() ;
1629 }
1630
1631 void wxBitmap::UngetRawData(wxPixelDataBase& dataBase)
1632 {
1633 EndRawAccess() ;
1634 }
1635
1636 void wxBitmap::UseAlpha()
1637 {
1638 // remember that we are using alpha channel:
1639 // we'll need to create a proper mask in UngetRawData()
1640 M_BITMAPDATA->UseAlpha( true );
1641 }