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