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