]> git.saurik.com Git - wxWidgets.git/blob - src/osx/core/bitmap.cpp
loading png and jpg from resource bundle
[wxWidgets.git] / src / osx / core / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/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
31 #if wxOSX_USE_CARBON
32 #include "wx/osx/uma.h"
33 #else
34 #include "wx/osx/private.h"
35 #endif
36
37 #ifndef __WXOSX_IPHONE__
38 #include <QuickTime/QuickTime.h>
39 #endif
40
41 CGColorSpaceRef wxMacGetGenericRGBColorSpace();
42 CGDataProviderRef wxMacCGDataProviderCreateWithMemoryBuffer( const wxMemoryBuffer& buf );
43
44 // Implementation Notes
45 // --------------------
46 //
47 // we are always working with a 32 bit deep pixel buffer
48 // under QuickDraw its alpha parts are going to be ignored in the GWorld,
49 // therefore we have a separate GWorld there for blitting the mask in
50
51 // under Quartz then content is transformed into a CGImageRef representing the same data
52 // which can be transferred to the GPU by the OS for fast rendering
53
54 class WXDLLEXPORT wxBitmapRefData: public wxGDIRefData
55 {
56 friend class WXDLLIMPEXP_FWD_CORE wxIcon;
57 friend class WXDLLIMPEXP_FWD_CORE wxCursor;
58 public:
59 wxBitmapRefData(int width , int height , int depth);
60 wxBitmapRefData(CGImageRef image);
61 wxBitmapRefData();
62 wxBitmapRefData(const wxBitmapRefData &tocopy);
63
64 virtual ~wxBitmapRefData();
65
66 virtual bool IsOk() const { return m_ok; }
67
68 void Free();
69 void SetOk( bool isOk) { m_ok = isOk; }
70
71 void SetWidth( int width ) { m_width = width; }
72 void SetHeight( int height ) { m_height = height; }
73 void SetDepth( int depth ) { m_depth = depth; }
74
75 int GetWidth() const { return m_width; }
76 int GetHeight() const { return m_height; }
77 int GetDepth() const { return m_depth; }
78
79 void *GetRawAccess() const;
80 void *BeginRawAccess();
81 void EndRawAccess();
82
83 bool HasAlpha() const { return m_hasAlpha; }
84 void UseAlpha( bool useAlpha );
85
86 public:
87 #if wxUSE_PALETTE
88 wxPalette m_bitmapPalette;
89 #endif // wxUSE_PALETTE
90
91 wxMask * m_bitmapMask; // Optional mask
92 CGImageRef CreateCGImage() const;
93
94 // returns true if the bitmap has a size that
95 // can be natively transferred into a true icon
96 // if no is returned GetIconRef will still produce
97 // an icon but it will be generated via a PICT and
98 // rescaled to 16 x 16
99 bool HasNativeSize();
100
101 // caller should increase ref count if needed longer
102 // than the bitmap exists
103 IconRef GetIconRef();
104
105 #ifndef __WXOSX_IPHONE__
106 // returns a Pict from the bitmap content
107 PicHandle GetPictHandle();
108 #endif
109
110 CGContextRef GetBitmapContext() const;
111
112 int GetBytesPerRow() const { return m_bytesPerRow; }
113 private :
114 bool Create(int width , int height , int depth);
115 bool Create( CGImageRef image );
116 void Init();
117
118 int m_width;
119 int m_height;
120 int m_bytesPerRow;
121 int m_depth;
122 bool m_hasAlpha;
123 wxMemoryBuffer m_memBuf;
124 int m_rawAccessCount;
125 bool m_ok;
126 mutable CGImageRef m_cgImageRef;
127
128 IconRef m_iconRef;
129 #ifndef __WXOSX_IPHONE__
130 PicHandle m_pictHandle;
131 #endif
132 CGContextRef m_hBitmap;
133 };
134
135
136 #define wxOSX_USE_PREMULTIPLIED_ALPHA 1
137 static const int kBestByteAlignement = 16;
138 static const int kMaskBytesPerPixel = 1;
139
140 static int GetBestBytesPerRow( int rawBytes )
141 {
142 return (((rawBytes)+kBestByteAlignement-1) & ~(kBestByteAlignement-1) );
143 }
144
145 #if wxUSE_GUI && !defined(__WXOSX_IPHONE__)
146
147 // this is used for more controls than just the wxBitmap button, also for notebooks etc
148
149 void wxMacCreateBitmapButton( ControlButtonContentInfo*info , const wxBitmap& bitmap , int forceType )
150 {
151 memset( info , 0 , sizeof(ControlButtonContentInfo) ) ;
152 if ( bitmap.Ok() )
153 {
154 wxBitmapRefData * bmap = bitmap.GetBitmapData() ;
155 if ( bmap == NULL )
156 return ;
157
158 if ( forceType == 0 )
159 {
160 forceType = kControlContentCGImageRef;
161 }
162
163 if ( forceType == kControlContentIconRef )
164 {
165 wxBitmap scaleBmp ;
166 wxBitmapRefData* bmp = bmap ;
167
168 if ( !bmap->HasNativeSize() )
169 {
170 // as PICT conversion will only result in a 16x16 icon, let's attempt
171 // a few scales for better results
172
173 int w = bitmap.GetWidth() ;
174 int h = bitmap.GetHeight() ;
175 int sz = wxMax( w , h ) ;
176 if ( sz == 24 || sz == 64 )
177 {
178 scaleBmp = wxBitmap( bitmap.ConvertToImage().Scale( w * 2 , h * 2 ) ) ;
179 bmp = scaleBmp.GetBitmapData() ;
180 }
181 }
182
183 info->contentType = kControlContentIconRef ;
184 info->u.iconRef = bmp->GetIconRef() ;
185 AcquireIconRef( info->u.iconRef ) ;
186 }
187 else if ( forceType == kControlContentCGImageRef )
188 {
189 info->contentType = kControlContentCGImageRef ;
190 info->u.imageRef = (CGImageRef) bmap->CreateCGImage() ;
191 }
192 else
193 {
194 #ifndef __LP64__
195 info->contentType = kControlContentPictHandle ;
196 info->u.picture = bmap->GetPictHandle() ;
197 #endif
198 }
199 }
200 }
201
202 CGImageRef wxMacCreateCGImageFromBitmap( const wxBitmap& bitmap )
203 {
204 wxBitmapRefData * bmap = bitmap.GetBitmapData() ;
205 if ( bmap == NULL )
206 return NULL ;
207 return (CGImageRef) bmap->CreateCGImage();
208 }
209
210 void wxMacReleaseBitmapButton( ControlButtonContentInfo*info )
211 {
212 if ( info->contentType == kControlContentIconRef )
213 {
214 ReleaseIconRef( info->u.iconRef ) ;
215 }
216 else if ( info->contentType == kControlNoContent )
217 {
218 // there's no bitmap at all, fall through silently
219 }
220 else if ( info->contentType == kControlContentPictHandle )
221 {
222 // owned by the bitmap, no release here
223 }
224 else if ( info->contentType == kControlContentCGImageRef )
225 {
226 CGImageRelease( info->u.imageRef ) ;
227 }
228 else
229 {
230 wxFAIL_MSG(wxT("Unexpected bitmap type") ) ;
231 }
232 }
233
234 #endif //wxUSE_BMPBUTTON
235
236 #define M_BITMAPDATA ((wxBitmapRefData *)m_refData)
237
238 void wxBitmapRefData::Init()
239 {
240 m_width = 0 ;
241 m_height = 0 ;
242 m_depth = 0 ;
243 m_bytesPerRow = 0;
244 m_ok = false ;
245 m_bitmapMask = NULL ;
246 m_cgImageRef = NULL ;
247
248 #ifndef __WXOSX_IPHONE__
249 m_iconRef = NULL ;
250 m_pictHandle = NULL ;
251 #endif
252 m_hBitmap = NULL ;
253
254 m_rawAccessCount = 0 ;
255 m_hasAlpha = false;
256 }
257
258 wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData &tocopy)
259 {
260 Init();
261 Create(tocopy.m_width, tocopy.m_height, tocopy.m_depth);
262
263 if (tocopy.m_bitmapMask)
264 m_bitmapMask = new wxMask(*tocopy.m_bitmapMask);
265 else if (tocopy.m_hasAlpha)
266 UseAlpha(true);
267
268 unsigned char* dest = (unsigned char*)GetRawAccess();
269 unsigned char* source = (unsigned char*)tocopy.GetRawAccess();
270 size_t numbytes = m_bytesPerRow * m_height;
271 memcpy( dest, source, numbytes );
272 }
273
274 wxBitmapRefData::wxBitmapRefData()
275 {
276 Init() ;
277 }
278
279 wxBitmapRefData::wxBitmapRefData( int w , int h , int d )
280 {
281 Init() ;
282 Create( w , h , d ) ;
283 }
284
285 wxBitmapRefData::wxBitmapRefData(CGImageRef image)
286 {
287 Init();
288 Create( image );
289 }
290 // code from Technical Q&A QA1509
291
292 bool wxBitmapRefData::Create(CGImageRef image)
293 {
294 m_width = CGImageGetWidth(image);
295 m_height = CGImageGetHeight(image);
296 m_depth = 32;
297 m_hBitmap = NULL;
298
299 m_bytesPerRow = GetBestBytesPerRow( m_width * 4 ) ;
300 size_t size = m_bytesPerRow * m_height ;
301 void* data = m_memBuf.GetWriteBuf( size ) ;
302 if ( data != NULL )
303 {
304 memset( data , 0 , size ) ;
305 m_memBuf.UngetWriteBuf( size ) ;
306 CGImageAlphaInfo alpha = CGImageGetAlphaInfo(image);
307 if ( alpha == kCGImageAlphaNone || alpha == kCGImageAlphaNoneSkipLast || alpha == kCGImageAlphaNoneSkipLast )
308 {
309 m_hBitmap = CGBitmapContextCreate((char*) data, m_width, m_height, 8, m_bytesPerRow, wxMacGetGenericRGBColorSpace(), kCGImageAlphaNoneSkipFirst );
310 }
311 else
312 {
313 m_hasAlpha = true;
314 m_hBitmap = CGBitmapContextCreate((char*) data, m_width, m_height, 8, m_bytesPerRow, wxMacGetGenericRGBColorSpace(), kCGImageAlphaPremultipliedFirst );
315 }
316 CGRect rect = {{0,0},{m_width,m_height}};
317 CGContextDrawImage(m_hBitmap, rect, image);
318
319 wxASSERT_MSG( m_hBitmap , wxT("Unable to create CGBitmapContext context") ) ;
320 CGContextTranslateCTM( m_hBitmap, 0, m_height );
321 CGContextScaleCTM( m_hBitmap, 1, -1 );
322 } /* data != NULL */
323 m_ok = ( m_hBitmap != NULL ) ;
324
325 return m_ok ;
326
327 }
328
329 bool wxBitmapRefData::Create( int w , int h , int d )
330 {
331 m_width = wxMax(1, w);
332 m_height = wxMax(1, h);
333 m_depth = d ;
334 m_hBitmap = NULL ;
335
336 m_bytesPerRow = GetBestBytesPerRow( m_width * 4 ) ;
337 size_t size = m_bytesPerRow * m_height ;
338 void* data = m_memBuf.GetWriteBuf( size ) ;
339 if ( data != NULL )
340 {
341 memset( data , 0 , size ) ;
342 m_memBuf.UngetWriteBuf( size ) ;
343
344 m_hBitmap = CGBitmapContextCreate((char*) data, m_width, m_height, 8, m_bytesPerRow, wxMacGetGenericRGBColorSpace(), kCGImageAlphaNoneSkipFirst );
345 wxASSERT_MSG( m_hBitmap , wxT("Unable to create CGBitmapContext context") ) ;
346 CGContextTranslateCTM( m_hBitmap, 0, m_height );
347 CGContextScaleCTM( m_hBitmap, 1, -1 );
348 } /* data != NULL */
349 m_ok = ( m_hBitmap != NULL ) ;
350
351 return m_ok ;
352 }
353
354 void wxBitmapRefData::UseAlpha( bool use )
355 {
356 if ( m_hasAlpha == use )
357 return ;
358
359 m_hasAlpha = use ;
360
361 CGContextRelease( m_hBitmap );
362 m_hBitmap = CGBitmapContextCreate((char*) m_memBuf.GetData(), m_width, m_height, 8, m_bytesPerRow, wxMacGetGenericRGBColorSpace(), m_hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst );
363 wxASSERT_MSG( m_hBitmap , wxT("Unable to create CGBitmapContext context") ) ;
364 CGContextTranslateCTM( m_hBitmap, 0, m_height );
365 CGContextScaleCTM( m_hBitmap, 1, -1 );
366 }
367
368 void *wxBitmapRefData::GetRawAccess() const
369 {
370 wxCHECK_MSG( IsOk(), NULL , wxT("invalid bitmap") ) ;
371 return m_memBuf.GetData() ;
372 }
373
374 void *wxBitmapRefData::BeginRawAccess()
375 {
376 wxCHECK_MSG( IsOk(), NULL, wxT("invalid bitmap") ) ;
377 wxASSERT( m_rawAccessCount == 0 ) ;
378 #ifndef __WXOSX_IPHONE__
379 wxASSERT_MSG( m_pictHandle == NULL && m_iconRef == NULL ,
380 wxT("Currently, modifing bitmaps that are used in controls already is not supported") ) ;
381 #endif
382 ++m_rawAccessCount ;
383
384 // we must destroy an existing cached image, as
385 // the bitmap data may change now
386 if ( m_cgImageRef )
387 {
388 CGImageRelease( m_cgImageRef ) ;
389 m_cgImageRef = NULL ;
390 }
391
392 return m_memBuf.GetData() ;
393 }
394
395 void wxBitmapRefData::EndRawAccess()
396 {
397 wxCHECK_RET( IsOk() , wxT("invalid bitmap") ) ;
398 wxASSERT( m_rawAccessCount == 1 ) ;
399
400 --m_rawAccessCount ;
401 }
402
403 bool wxBitmapRefData::HasNativeSize()
404 {
405 int w = GetWidth() ;
406 int h = GetHeight() ;
407 int sz = wxMax( w , h ) ;
408
409 return ( sz == 128 || sz == 48 || sz == 32 || sz == 16 );
410 }
411
412 #ifndef __WXOSX_IPHONE__
413 IconRef wxBitmapRefData::GetIconRef()
414 {
415 if ( m_iconRef == NULL )
416 {
417 // Create Icon Family Handle
418
419 IconFamilyHandle iconFamily = (IconFamilyHandle) NewHandle( 0 );
420
421 int w = GetWidth() ;
422 int h = GetHeight() ;
423 int sz = wxMax( w , h ) ;
424
425 OSType dataType = 0 ;
426 OSType maskType = 0 ;
427
428 switch (sz)
429 {
430 case 128:
431 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
432 if ( UMAGetSystemVersion() >= 0x1050 )
433 {
434 dataType = kIconServices128PixelDataARGB ;
435 }
436 else
437 #endif
438 {
439 dataType = kThumbnail32BitData ;
440 maskType = kThumbnail8BitMask ;
441 }
442 break;
443
444 case 48:
445 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
446 if ( UMAGetSystemVersion() >= 0x1050 )
447 {
448 dataType = kIconServices48PixelDataARGB ;
449 }
450 else
451 #endif
452 {
453 dataType = kHuge32BitData ;
454 maskType = kHuge8BitMask ;
455 }
456 break;
457
458 case 32:
459 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
460 if ( UMAGetSystemVersion() >= 0x1050 )
461 {
462 dataType = kIconServices32PixelDataARGB ;
463 }
464 else
465 #endif
466 {
467 dataType = kLarge32BitData ;
468 maskType = kLarge8BitMask ;
469 }
470 break;
471
472 case 16:
473 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
474 if ( UMAGetSystemVersion() >= 0x1050 )
475 {
476 dataType = kIconServices16PixelDataARGB ;
477 }
478 else
479 #endif
480 {
481 dataType = kSmall32BitData ;
482 maskType = kSmall8BitMask ;
483 }
484 break;
485
486 default:
487 break;
488 }
489
490 if ( dataType != 0 )
491 {
492 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
493 if ( maskType == 0 && UMAGetSystemVersion() >= 0x1050 )
494 {
495 size_t datasize = sz * sz * 4 ;
496 Handle data = NewHandle( datasize ) ;
497 HLock( data ) ;
498 unsigned char* ptr = (unsigned char*) *data ;
499 memset( ptr, 0, datasize );
500 bool hasAlpha = HasAlpha() ;
501 wxMask *mask = m_bitmapMask ;
502 unsigned char * sourcePtr = (unsigned char*) GetRawAccess() ;
503 unsigned char * masksourcePtr = mask ? (unsigned char*) mask->GetRawAccess() : NULL ;
504
505 for ( int y = 0 ; y < h ; ++y, sourcePtr += m_bytesPerRow , masksourcePtr += mask ? mask->GetBytesPerRow() : 0 )
506 {
507 unsigned char * source = sourcePtr;
508 unsigned char * masksource = masksourcePtr;
509 unsigned char * dest = ptr + y * sz * 4 ;
510 unsigned char a, r, g, b;
511
512 for ( int x = 0 ; x < w ; ++x )
513 {
514 a = *source ++ ;
515 r = *source ++ ;
516 g = *source ++ ;
517 b = *source ++ ;
518
519 if ( mask )
520 {
521 a = 0xFF - *masksource++ ;
522 }
523 else if ( !hasAlpha )
524 a = 0xFF ;
525 else
526 {
527 #if wxOSX_USE_PREMULTIPLIED_ALPHA
528 // this must be non-premultiplied data
529 if ( a != 0xFF && a!= 0 )
530 {
531 r = r * 255 / a;
532 g = g * 255 / a;
533 b = b * 255 / a;
534 }
535 #endif
536 }
537 *dest++ = a ;
538 *dest++ = r ;
539 *dest++ = g ;
540 *dest++ = b ;
541
542 }
543 }
544 HUnlock( data );
545
546 OSStatus err = SetIconFamilyData( iconFamily, dataType , data );
547 if ( err != noErr )
548 {
549 wxFAIL_MSG("Error when adding bitmap");
550 }
551
552 DisposeHandle( data );
553 }
554 else
555 #endif
556 {
557 // setup the header properly
558
559 Handle data = NULL ;
560 Handle maskdata = NULL ;
561 unsigned char * maskptr = NULL ;
562 unsigned char * ptr = NULL ;
563 size_t datasize, masksize ;
564
565 datasize = sz * sz * 4 ;
566 data = NewHandle( datasize ) ;
567 HLock( data ) ;
568 ptr = (unsigned char*) *data ;
569 memset( ptr , 0, datasize ) ;
570
571 masksize = sz * sz ;
572 maskdata = NewHandle( masksize ) ;
573 HLock( maskdata ) ;
574 maskptr = (unsigned char*) *maskdata ;
575 memset( maskptr , 0 , masksize ) ;
576
577 bool hasAlpha = HasAlpha() ;
578 wxMask *mask = m_bitmapMask ;
579 unsigned char * sourcePtr = (unsigned char*) GetRawAccess() ;
580 unsigned char * masksourcePtr = mask ? (unsigned char*) mask->GetRawAccess() : NULL ;
581
582 for ( int y = 0 ; y < h ; ++y, sourcePtr += m_bytesPerRow , masksourcePtr += mask ? mask->GetBytesPerRow() : 0 )
583 {
584 unsigned char * source = sourcePtr;
585 unsigned char * masksource = masksourcePtr;
586 unsigned char * dest = ptr + y * sz * 4 ;
587 unsigned char * maskdest = maskptr + y * sz ;
588 unsigned char a, r, g, b;
589
590 for ( int x = 0 ; x < w ; ++x )
591 {
592 a = *source ++ ;
593 r = *source ++ ;
594 g = *source ++ ;
595 b = *source ++ ;
596
597 *dest++ = 0 ;
598 *dest++ = r ;
599 *dest++ = g ;
600 *dest++ = b ;
601
602 if ( mask )
603 *maskdest++ = 0xFF - *masksource++ ;
604 else if ( hasAlpha )
605 *maskdest++ = a ;
606 else
607 *maskdest++ = 0xFF ;
608 }
609 }
610
611 OSStatus err = SetIconFamilyData( iconFamily, dataType , data ) ;
612 wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;
613
614 err = SetIconFamilyData( iconFamily, maskType , maskdata ) ;
615 wxASSERT_MSG( err == noErr , wxT("Error when adding mask") ) ;
616
617 HUnlock( data ) ;
618 HUnlock( maskdata ) ;
619 DisposeHandle( data ) ;
620 DisposeHandle( maskdata ) ;
621 }
622 }
623 else
624 {
625 PicHandle pic = GetPictHandle() ;
626 SetIconFamilyData( iconFamily, 'PICT' , (Handle) pic ) ;
627 }
628 // transform into IconRef
629
630 // cleaner version existing from 10.3 upwards
631 HLock((Handle) iconFamily);
632 OSStatus err = GetIconRefFromIconFamilyPtr( *iconFamily, GetHandleSize((Handle) iconFamily), &m_iconRef );
633 HUnlock((Handle) iconFamily);
634 DisposeHandle( (Handle) iconFamily ) ;
635
636 wxCHECK_MSG( err == noErr, NULL, wxT("Error when constructing icon ref") );
637 }
638
639 return m_iconRef ;
640 }
641
642 PicHandle wxBitmapRefData::GetPictHandle()
643 {
644 if ( m_pictHandle == NULL )
645 {
646 #ifndef __LP64__
647 GraphicsExportComponent exporter = 0;
648 OSStatus err = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePicture, &exporter);
649 if (noErr == err)
650 {
651 m_pictHandle = (PicHandle) NewHandle(0);
652 if ( m_pictHandle )
653 {
654 // QT does not correctly export the mask
655 // TODO if we get around to it create a synthetic PICT with the CopyBits and Mask commands
656 CGImageRef imageRef = CreateCGImage();
657 err = GraphicsExportSetInputCGImage( exporter, imageRef );
658 err = GraphicsExportSetOutputHandle(exporter, (Handle)m_pictHandle);
659 err = GraphicsExportDoExport(exporter, NULL);
660 CGImageRelease( imageRef );
661
662 size_t handleSize = GetHandleSize( (Handle) m_pictHandle );
663 // the 512 bytes header is only needed for pict files, but not in memory
664 if ( handleSize >= 512 )
665 {
666 memmove( *m_pictHandle , (char*)(*m_pictHandle)+512, handleSize - 512 );
667 SetHandleSize( (Handle) m_pictHandle, handleSize - 512 );
668 }
669 }
670 CloseComponent( exporter );
671 }
672 #endif
673 }
674
675 return m_pictHandle ;
676 }
677 #endif
678
679 CGImageRef wxBitmapRefData::CreateCGImage() const
680 {
681 wxASSERT( m_ok ) ;
682 wxASSERT( m_rawAccessCount >= 0 ) ;
683 CGImageRef image ;
684 if ( m_rawAccessCount > 0 || m_cgImageRef == NULL )
685 {
686 if ( m_depth != 1 && m_bitmapMask == NULL )
687 {
688 #if 0
689 // in order for this code to work properly, wxMask would have to invert black and white
690 // in the native bitmap
691 if ( m_bitmapMask )
692 {
693 CGImageRef tempImage = CGBitmapContextCreateImage( m_hBitmap );
694 CGImageRef tempMask = CGBitmapContextCreateImage((CGContextRef) m_bitmapMask->GetHBITMAP() );
695 image = CGImageCreateWithMask( tempImage, tempMask );
696 CGImageRelease(tempMask);
697 CGImageRelease(tempImage);
698 }
699 else
700 #endif
701 image = CGBitmapContextCreateImage( m_hBitmap );
702 }
703 else
704 {
705 size_t imageSize = m_height * m_bytesPerRow ;
706 void * dataBuffer = m_memBuf.GetData() ;
707 int w = m_width ;
708 int h = m_height ;
709 CGImageAlphaInfo alphaInfo = kCGImageAlphaNoneSkipFirst ;
710 wxMemoryBuffer membuf;
711
712 if ( m_bitmapMask )
713 {
714 alphaInfo = kCGImageAlphaFirst ;
715 unsigned char *destalphastart = (unsigned char*) membuf.GetWriteBuf( imageSize ) ;
716 memcpy( destalphastart , dataBuffer , imageSize ) ;
717 unsigned char *sourcemaskstart = (unsigned char *) m_bitmapMask->GetRawAccess() ;
718 int maskrowbytes = m_bitmapMask->GetBytesPerRow() ;
719 for ( int y = 0 ; y < h ; ++y , destalphastart += m_bytesPerRow, sourcemaskstart += maskrowbytes)
720 {
721 unsigned char *sourcemask = sourcemaskstart ;
722 unsigned char *destalpha = destalphastart ;
723 for ( int x = 0 ; x < w ; ++x , sourcemask += kMaskBytesPerPixel , destalpha += 4 )
724 {
725 *destalpha = 0xFF - *sourcemask ;
726 }
727 }
728 membuf.UngetWriteBuf( imageSize );
729 }
730 else
731 {
732 if ( m_hasAlpha )
733 {
734 #if wxOSX_USE_PREMULTIPLIED_ALPHA
735 alphaInfo = kCGImageAlphaPremultipliedFirst ;
736 #else
737 alphaInfo = kCGImageAlphaFirst ;
738 #endif
739 }
740
741 membuf = m_memBuf;
742 }
743
744 CGDataProviderRef dataProvider = NULL ;
745 if ( m_depth == 1 )
746 {
747 // TODO CHECK ALIGNMENT
748 wxMemoryBuffer maskBuf;
749 unsigned char * maskBufData = (unsigned char*) maskBuf.GetWriteBuf( m_width * m_height );
750 unsigned char * bufData = (unsigned char *) membuf.GetData() ;
751 // copy one color component
752 size_t i = 0;
753 for( int y = 0 ; y < m_height ; bufData+= m_bytesPerRow, ++y )
754 {
755 unsigned char *bufDataIter = bufData+3;
756 for ( int x = 0 ; x < m_width ; bufDataIter += 4, ++x, ++i )
757 {
758 maskBufData[i] = *bufDataIter;
759 }
760 }
761 maskBuf.UngetWriteBuf( m_width * m_height );
762
763 dataProvider =
764 wxMacCGDataProviderCreateWithMemoryBuffer( maskBuf );
765
766 image = ::CGImageMaskCreate( w, h, 8, 8, m_width , dataProvider, NULL, false );
767 }
768 else
769 {
770 CGColorSpaceRef colorSpace = wxMacGetGenericRGBColorSpace();
771 dataProvider = wxMacCGDataProviderCreateWithMemoryBuffer( membuf );
772 image =
773 ::CGImageCreate(
774 w, h, 8 , 32 , m_bytesPerRow , colorSpace, alphaInfo ,
775 dataProvider, NULL , false , kCGRenderingIntentDefault );
776 }
777 CGDataProviderRelease( dataProvider);
778 }
779 }
780 else
781 {
782 image = m_cgImageRef ;
783 CGImageRetain( image ) ;
784 }
785
786 if ( m_rawAccessCount == 0 && m_cgImageRef == NULL)
787 {
788 // we keep it for later use
789 m_cgImageRef = image ;
790 CGImageRetain( image ) ;
791 }
792
793 return image ;
794 }
795
796 CGContextRef wxBitmapRefData::GetBitmapContext() const
797 {
798 return m_hBitmap;
799 }
800
801 void wxBitmapRefData::Free()
802 {
803 wxASSERT_MSG( m_rawAccessCount == 0 , wxT("Bitmap still selected when destroyed") ) ;
804
805 if ( m_cgImageRef )
806 {
807 CGImageRelease( m_cgImageRef ) ;
808 m_cgImageRef = NULL ;
809 }
810 #ifndef __WXOSX_IPHONE__
811 if ( m_iconRef )
812 {
813 ReleaseIconRef( m_iconRef ) ;
814 m_iconRef = NULL ;
815 }
816
817 #ifndef __LP64__
818 if ( m_pictHandle )
819 {
820 KillPicture( m_pictHandle ) ;
821 m_pictHandle = NULL ;
822 }
823 #endif
824 #endif
825 if ( m_hBitmap )
826 {
827 CGContextRelease(m_hBitmap);
828 m_hBitmap = NULL ;
829 }
830
831 wxDELETE(m_bitmapMask);
832 }
833
834 wxBitmapRefData::~wxBitmapRefData()
835 {
836 Free() ;
837 }
838
839
840
841 // ----------------------------------------------------------------------------
842 // wxBitmap
843 // ----------------------------------------------------------------------------
844
845 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
846 {
847 bool created = false ;
848 int w = icon.GetWidth() ;
849 int h = icon.GetHeight() ;
850
851 Create( w , h ) ;
852 #ifdef __WXOSX_CARBON__
853 if ( w == h && ( w == 16 || w == 32 || w == 48 || w == 128 ) )
854 {
855 IconFamilyHandle iconFamily = NULL ;
856 Handle imagehandle = NewHandle( 0 ) ;
857 Handle maskhandle = NewHandle( 0 ) ;
858
859 OSType maskType = 0;
860 OSType dataType = 0;
861 IconSelectorValue selector = 0 ;
862
863 switch (w)
864 {
865 case 128:
866 dataType = kThumbnail32BitData ;
867 maskType = kThumbnail8BitMask ;
868 selector = kSelectorAllAvailableData ;
869 break;
870
871 case 48:
872 dataType = kHuge32BitData ;
873 maskType = kHuge8BitMask ;
874 selector = kSelectorHuge32Bit | kSelectorHuge8BitMask ;
875 break;
876
877 case 32:
878 dataType = kLarge32BitData ;
879 maskType = kLarge8BitMask ;
880 selector = kSelectorLarge32Bit | kSelectorLarge8BitMask ;
881 break;
882
883 case 16:
884 dataType = kSmall32BitData ;
885 maskType = kSmall8BitMask ;
886 selector = kSelectorSmall32Bit | kSelectorSmall8BitMask ;
887 break;
888
889 default:
890 break;
891 }
892
893 OSStatus err = IconRefToIconFamily( MAC_WXHICON(icon.GetHICON()) , selector , &iconFamily ) ;
894
895 err = GetIconFamilyData( iconFamily , dataType , imagehandle ) ;
896 err = GetIconFamilyData( iconFamily , maskType , maskhandle ) ;
897 size_t imagehandlesize = GetHandleSize( imagehandle ) ;
898 size_t maskhandlesize = GetHandleSize( maskhandle ) ;
899
900 if ( imagehandlesize != 0 && maskhandlesize != 0 )
901 {
902 wxASSERT( GetHandleSize( imagehandle ) == w * 4 * h ) ;
903 wxASSERT( GetHandleSize( maskhandle ) == w * h ) ;
904
905 UseAlpha() ;
906
907 unsigned char *source = (unsigned char *) *imagehandle ;
908 unsigned char *sourcemask = (unsigned char *) *maskhandle ;
909 unsigned char* destination = (unsigned char*) BeginRawAccess() ;
910
911 for ( int y = 0 ; y < h ; ++y )
912 {
913 for ( int x = 0 ; x < w ; ++x )
914 {
915 unsigned char a = *sourcemask++;
916 *destination++ = a;
917 source++ ;
918 #if wxOSX_USE_PREMULTIPLIED_ALPHA
919 *destination++ = ( (*source++) * a + 127 ) / 255;
920 *destination++ = ( (*source++) * a + 127 ) / 255;
921 *destination++ = ( (*source++) * a + 127 ) / 255;
922 #else
923 *destination++ = *source++ ;
924 *destination++ = *source++ ;
925 *destination++ = *source++ ;
926 #endif
927 }
928 }
929
930 EndRawAccess() ;
931 DisposeHandle( imagehandle ) ;
932 DisposeHandle( maskhandle ) ;
933 created = true ;
934 }
935
936 DisposeHandle( (Handle) iconFamily ) ;
937 }
938 #endif
939 if ( !created )
940 {
941 wxMemoryDC dc ;
942 dc.SelectObject( *this ) ;
943 dc.DrawIcon( icon , 0 , 0 ) ;
944 dc.SelectObject( wxNullBitmap ) ;
945 }
946
947 return true;
948 }
949
950 wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
951 {
952 wxBitmapRefData* bitmapRefData;
953
954 m_refData = bitmapRefData = new wxBitmapRefData( the_width , the_height , no_bits ) ;
955
956 if (bitmapRefData->IsOk())
957 {
958 if ( no_bits == 1 )
959 {
960 int linesize = ( the_width / (sizeof(unsigned char) * 8)) ;
961 if ( the_width % (sizeof(unsigned char) * 8) )
962 linesize += sizeof(unsigned char);
963
964 unsigned char* linestart = (unsigned char*) bits ;
965 unsigned char* destptr = (unsigned char*) BeginRawAccess() ;
966
967 for ( int y = 0 ; y < the_height ; ++y , linestart += linesize, destptr += M_BITMAPDATA->GetBytesPerRow() )
968 {
969 unsigned char* destination = destptr;
970 int index, bit, mask;
971
972 for ( int x = 0 ; x < the_width ; ++x )
973 {
974 index = x / 8 ;
975 bit = x % 8 ;
976 mask = 1 << bit ;
977
978 if ( linestart[index] & mask )
979 {
980 *destination++ = 0xFF ;
981 *destination++ = 0 ;
982 *destination++ = 0 ;
983 *destination++ = 0 ;
984 }
985 else
986 {
987 *destination++ = 0xFF ;
988 *destination++ = 0xFF ;
989 *destination++ = 0xFF ;
990 *destination++ = 0xFF ;
991 }
992 }
993 }
994
995 EndRawAccess() ;
996 }
997 else
998 {
999 wxFAIL_MSG(wxT("multicolor BITMAPs not yet implemented"));
1000 }
1001 } /* bitmapRefData->IsOk() */
1002 }
1003
1004 wxBitmap::wxBitmap(const void* data, wxBitmapType type, int width, int height, int depth)
1005 {
1006 (void) Create(data, type, width, height, depth);
1007 }
1008
1009 wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
1010 {
1011 LoadFile(filename, type);
1012 }
1013
1014 wxGDIRefData* wxBitmap::CreateGDIRefData() const
1015 {
1016 return new wxBitmapRefData;
1017 }
1018
1019 wxGDIRefData* wxBitmap::CloneGDIRefData(const wxGDIRefData* data) const
1020 {
1021 return new wxBitmapRefData(*static_cast<const wxBitmapRefData *>(data));
1022 }
1023
1024 void * wxBitmap::GetRawAccess() const
1025 {
1026 wxCHECK_MSG( Ok() , NULL , wxT("invalid bitmap") ) ;
1027
1028 return M_BITMAPDATA->GetRawAccess() ;
1029 }
1030
1031 void * wxBitmap::BeginRawAccess()
1032 {
1033 wxCHECK_MSG( Ok() , NULL , wxT("invalid bitmap") ) ;
1034
1035 return M_BITMAPDATA->BeginRawAccess() ;
1036 }
1037
1038 void wxBitmap::EndRawAccess()
1039 {
1040 wxCHECK_RET( Ok() , wxT("invalid bitmap") ) ;
1041
1042 M_BITMAPDATA->EndRawAccess() ;
1043 }
1044
1045 CGImageRef wxBitmap::CreateCGImage() const
1046 {
1047 wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ;
1048
1049 return M_BITMAPDATA->CreateCGImage() ;
1050 }
1051
1052 #ifndef __WXOSX_IPHONE__
1053 IconRef wxBitmap::GetIconRef() const
1054 {
1055 wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ;
1056
1057 return M_BITMAPDATA->GetIconRef() ;
1058 }
1059
1060 IconRef wxBitmap::CreateIconRef() const
1061 {
1062 IconRef icon = GetIconRef();
1063 verify_noerr( AcquireIconRef(icon) );
1064 return icon;
1065 }
1066 #endif
1067
1068 #if wxOSX_USE_COCOA
1069
1070 WX_NSImage wxBitmap::GetNSImage() const
1071 {
1072 wxCFRef< CGImageRef > cgimage(CreateCGImage());
1073 return wxOSXGetNSImageFromCGImage( cgimage );
1074 }
1075
1076 #endif
1077
1078 #if wxOSX_USE_IPHONE
1079
1080 WX_UIImage wxBitmap::GetUIImage() const
1081 {
1082 wxCFRef< CGImageRef > cgimage(CreateCGImage());
1083 return wxOSXGetUIImageFromCGImage( cgimage );
1084 }
1085
1086 #endif
1087 wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const
1088 {
1089 wxCHECK_MSG( Ok() &&
1090 (rect.x >= 0) && (rect.y >= 0) &&
1091 (rect.x+rect.width <= GetWidth()) &&
1092 (rect.y+rect.height <= GetHeight()),
1093 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
1094
1095 wxBitmap ret( rect.width, rect.height, GetDepth() );
1096 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
1097
1098 int destwidth = rect.width ;
1099 int destheight = rect.height ;
1100
1101 {
1102 unsigned char *sourcedata = (unsigned char*) GetRawAccess() ;
1103 unsigned char *destdata = (unsigned char*) ret.BeginRawAccess() ;
1104 wxASSERT( (sourcedata != NULL) && (destdata != NULL) ) ;
1105
1106 int sourcelinesize = GetBitmapData()->GetBytesPerRow() ;
1107 int destlinesize = ret.GetBitmapData()->GetBytesPerRow() ;
1108 unsigned char *source = sourcedata + rect.x * 4 + rect.y * sourcelinesize ;
1109 unsigned char *dest = destdata ;
1110
1111 for (int yy = 0; yy < destheight; ++yy, source += sourcelinesize , dest += destlinesize)
1112 {
1113 memcpy( dest , source , destlinesize ) ;
1114 }
1115 }
1116
1117 ret.EndRawAccess() ;
1118
1119 if ( M_BITMAPDATA->m_bitmapMask )
1120 {
1121 wxMemoryBuffer maskbuf ;
1122 int rowBytes = GetBestBytesPerRow( destwidth * kMaskBytesPerPixel );
1123 size_t maskbufsize = rowBytes * destheight ;
1124
1125 int sourcelinesize = M_BITMAPDATA->m_bitmapMask->GetBytesPerRow() ;
1126 int destlinesize = rowBytes ;
1127
1128 unsigned char *source = (unsigned char *) M_BITMAPDATA->m_bitmapMask->GetRawAccess() ;
1129 unsigned char *destdata = (unsigned char * ) maskbuf.GetWriteBuf( maskbufsize ) ;
1130 wxASSERT( (source != NULL) && (destdata != NULL) ) ;
1131
1132 source += rect.x * kMaskBytesPerPixel + rect.y * sourcelinesize ;
1133 unsigned char *dest = destdata ;
1134
1135 for (int yy = 0; yy < destheight; ++yy, source += sourcelinesize , dest += destlinesize)
1136 {
1137 memcpy( dest , source , destlinesize ) ;
1138 }
1139
1140 maskbuf.UngetWriteBuf( maskbufsize ) ;
1141 ret.SetMask( new wxMask( maskbuf , destwidth , destheight , rowBytes ) ) ;
1142 }
1143 else if ( HasAlpha() )
1144 ret.UseAlpha() ;
1145
1146 return ret;
1147 }
1148
1149 bool wxBitmap::Create(int w, int h, int d)
1150 {
1151 UnRef();
1152
1153 if ( d < 0 )
1154 d = wxDisplayDepth() ;
1155
1156 m_refData = new wxBitmapRefData( w , h , d );
1157
1158 return M_BITMAPDATA->IsOk() ;
1159 }
1160
1161
1162 bool wxBitmap::Create(CGImageRef image)
1163 {
1164 UnRef();
1165
1166 m_refData = new wxBitmapRefData( image );
1167
1168 return M_BITMAPDATA->IsOk() ;
1169 }
1170
1171 bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
1172 {
1173 UnRef();
1174
1175 wxBitmapHandler *handler = FindHandler(type);
1176
1177 if ( handler )
1178 {
1179 m_refData = new wxBitmapRefData;
1180
1181 return handler->LoadFile(this, filename, type, -1, -1);
1182 }
1183 else
1184 {
1185 #if wxUSE_IMAGE
1186 wxImage loadimage(filename, type);
1187 if (loadimage.Ok())
1188 {
1189 *this = loadimage;
1190
1191 return true;
1192 }
1193 #endif
1194 }
1195
1196 wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
1197
1198 return false;
1199 }
1200
1201 bool wxBitmap::Create(const void* data, wxBitmapType type, int width, int height, int depth)
1202 {
1203 UnRef();
1204
1205 m_refData = new wxBitmapRefData;
1206
1207 wxBitmapHandler *handler = FindHandler(type);
1208
1209 if ( handler == NULL )
1210 {
1211 wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
1212
1213 return false;
1214 }
1215
1216 return handler->Create(this, data, type, width, height, depth);
1217 }
1218
1219 #if wxUSE_IMAGE
1220
1221 wxBitmap::wxBitmap(const wxImage& image, int depth)
1222 {
1223 wxCHECK_RET( image.Ok(), wxT("invalid image") );
1224
1225 // width and height of the device-dependent bitmap
1226 int width = image.GetWidth();
1227 int height = image.GetHeight();
1228
1229 wxBitmapRefData* bitmapRefData;
1230
1231 m_refData = bitmapRefData = new wxBitmapRefData( width , height , depth ) ;
1232
1233 if ( bitmapRefData->IsOk())
1234 {
1235 // Create picture
1236
1237 bool hasAlpha = false ;
1238
1239 if ( image.HasMask() )
1240 {
1241 // takes precedence, don't mix with alpha info
1242 }
1243 else
1244 {
1245 hasAlpha = image.HasAlpha() ;
1246 }
1247
1248 if ( hasAlpha )
1249 UseAlpha() ;
1250
1251 unsigned char* destinationstart = (unsigned char*) BeginRawAccess() ;
1252 register unsigned char* data = image.GetData();
1253 if ( destinationstart != NULL && data != NULL )
1254 {
1255 const unsigned char *alpha = hasAlpha ? image.GetAlpha() : NULL ;
1256 for (int y = 0; y < height; destinationstart += M_BITMAPDATA->GetBytesPerRow(), y++)
1257 {
1258 unsigned char * destination = destinationstart;
1259 for (int x = 0; x < width; x++)
1260 {
1261 if ( hasAlpha )
1262 {
1263 const unsigned char a = *alpha++;
1264 *destination++ = a ;
1265
1266 #if wxOSX_USE_PREMULTIPLIED_ALPHA
1267 *destination++ = ((*data++) * a + 127) / 255 ;
1268 *destination++ = ((*data++) * a + 127) / 255 ;
1269 *destination++ = ((*data++) * a + 127) / 255 ;
1270 #else
1271 *destination++ = *data++ ;
1272 *destination++ = *data++ ;
1273 *destination++ = *data++ ;
1274 #endif
1275 }
1276 else
1277 {
1278 *destination++ = 0xFF ;
1279 *destination++ = *data++ ;
1280 *destination++ = *data++ ;
1281 *destination++ = *data++ ;
1282 }
1283 }
1284 }
1285
1286 EndRawAccess() ;
1287 }
1288 if ( image.HasMask() )
1289 SetMask( new wxMask( *this , wxColour( image.GetMaskRed() , image.GetMaskGreen() , image.GetMaskBlue() ) ) ) ;
1290 } /* bitmapRefData->IsOk() */
1291 }
1292
1293 wxImage wxBitmap::ConvertToImage() const
1294 {
1295 wxImage image;
1296
1297 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
1298
1299 // create an wxImage object
1300 int width = GetWidth();
1301 int height = GetHeight();
1302 image.Create( width, height );
1303
1304 unsigned char *data = image.GetData();
1305 wxCHECK_MSG( data, wxNullImage, wxT("Could not allocate data for image") );
1306
1307 unsigned char* sourcestart = (unsigned char*) GetRawAccess() ;
1308
1309 bool hasAlpha = false ;
1310 bool hasMask = false ;
1311 int maskBytesPerRow = 0 ;
1312 unsigned char *alpha = NULL ;
1313 unsigned char *mask = NULL ;
1314
1315 if ( HasAlpha() )
1316 hasAlpha = true ;
1317
1318 if ( GetMask() )
1319 {
1320 hasMask = true ;
1321 mask = (unsigned char*) GetMask()->GetRawAccess() ;
1322 maskBytesPerRow = GetMask()->GetBytesPerRow() ;
1323 }
1324
1325 if ( hasAlpha )
1326 {
1327 image.SetAlpha() ;
1328 alpha = image.GetAlpha() ;
1329 }
1330
1331 int index = 0;
1332
1333 // The following masking algorithm is the same as well in msw/gtk:
1334 // the colour used as transparent one in wxImage and the one it is
1335 // replaced with when it actually occurs in the bitmap
1336 static const int MASK_RED = 1;
1337 static const int MASK_GREEN = 2;
1338 static const int MASK_BLUE = 3;
1339 static const int MASK_BLUE_REPLACEMENT = 2;
1340
1341 for (int yy = 0; yy < height; yy++ , sourcestart += M_BITMAPDATA->GetBytesPerRow() , mask += maskBytesPerRow )
1342 {
1343 unsigned char * maskp = mask ;
1344 unsigned char * source = sourcestart;
1345 unsigned char a, r, g, b;
1346 long color;
1347
1348 for (int xx = 0; xx < width; xx++)
1349 {
1350 color = *((long*) source) ;
1351 #ifdef WORDS_BIGENDIAN
1352 a = ((color&0xFF000000) >> 24) ;
1353 r = ((color&0x00FF0000) >> 16) ;
1354 g = ((color&0x0000FF00) >> 8) ;
1355 b = (color&0x000000FF);
1356 #else
1357 b = ((color&0xFF000000) >> 24) ;
1358 g = ((color&0x00FF0000) >> 16) ;
1359 r = ((color&0x0000FF00) >> 8) ;
1360 a = (color&0x000000FF);
1361 #endif
1362 if ( hasMask )
1363 {
1364 if ( *maskp++ == 0xFF )
1365 {
1366 r = MASK_RED ;
1367 g = MASK_GREEN ;
1368 b = MASK_BLUE ;
1369 }
1370 else if ( r == MASK_RED && g == MASK_GREEN && b == MASK_BLUE )
1371 b = MASK_BLUE_REPLACEMENT ;
1372 }
1373 else if ( hasAlpha )
1374 {
1375 *alpha++ = a ;
1376 #if wxOSX_USE_PREMULTIPLIED_ALPHA
1377 // this must be non-premultiplied data
1378 if ( a != 0xFF && a!= 0 )
1379 {
1380 r = r * 255 / a;
1381 g = g * 255 / a;
1382 b = b * 255 / a;
1383 }
1384 #endif
1385 }
1386
1387 data[index ] = r ;
1388 data[index + 1] = g ;
1389 data[index + 2] = b ;
1390
1391 index += 3;
1392 source += 4 ;
1393 }
1394 }
1395
1396 if ( hasMask )
1397 image.SetMaskColour( MASK_RED, MASK_GREEN, MASK_BLUE );
1398
1399 return image;
1400 }
1401
1402 #endif //wxUSE_IMAGE
1403
1404 bool wxBitmap::SaveFile( const wxString& filename,
1405 wxBitmapType type, const wxPalette *palette ) const
1406 {
1407 bool success = false;
1408 wxBitmapHandler *handler = FindHandler(type);
1409
1410 if ( handler )
1411 {
1412 success = handler->SaveFile(this, filename, type, palette);
1413 }
1414 else
1415 {
1416 #if wxUSE_IMAGE
1417 wxImage image = ConvertToImage();
1418 success = image.SaveFile(filename, type);
1419 #else
1420 wxLogWarning(wxT("no bitmap handler for type %d defined."), type);
1421 #endif
1422 }
1423
1424 return success;
1425 }
1426
1427 int wxBitmap::GetHeight() const
1428 {
1429 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1430
1431 return M_BITMAPDATA->GetHeight();
1432 }
1433
1434 int wxBitmap::GetWidth() const
1435 {
1436 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1437
1438 return M_BITMAPDATA->GetWidth() ;
1439 }
1440
1441 int wxBitmap::GetDepth() const
1442 {
1443 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1444
1445 return M_BITMAPDATA->GetDepth();
1446 }
1447
1448 wxMask *wxBitmap::GetMask() const
1449 {
1450 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
1451
1452 return M_BITMAPDATA->m_bitmapMask;
1453 }
1454
1455 bool wxBitmap::HasAlpha() const
1456 {
1457 wxCHECK_MSG( Ok(), false , wxT("invalid bitmap") );
1458
1459 return M_BITMAPDATA->HasAlpha() ;
1460 }
1461
1462 void wxBitmap::SetWidth(int w)
1463 {
1464 AllocExclusive();
1465 M_BITMAPDATA->SetWidth(w);
1466 }
1467
1468 void wxBitmap::SetHeight(int h)
1469 {
1470 AllocExclusive();
1471 M_BITMAPDATA->SetHeight(h);
1472 }
1473
1474 void wxBitmap::SetDepth(int d)
1475 {
1476 AllocExclusive();
1477 M_BITMAPDATA->SetDepth(d);
1478 }
1479
1480 void wxBitmap::SetOk(bool isOk)
1481 {
1482 AllocExclusive();
1483 M_BITMAPDATA->SetOk(isOk);
1484 }
1485
1486 #if wxUSE_PALETTE
1487 wxPalette *wxBitmap::GetPalette() const
1488 {
1489 wxCHECK_MSG( Ok(), NULL, wxT("Invalid bitmap GetPalette()") );
1490
1491 return &M_BITMAPDATA->m_bitmapPalette;
1492 }
1493
1494 void wxBitmap::SetPalette(const wxPalette& palette)
1495 {
1496 AllocExclusive();
1497 M_BITMAPDATA->m_bitmapPalette = palette ;
1498 }
1499 #endif // wxUSE_PALETTE
1500
1501 void wxBitmap::SetMask(wxMask *mask)
1502 {
1503 AllocExclusive();
1504 // Remove existing mask if there is one.
1505 delete M_BITMAPDATA->m_bitmapMask;
1506
1507 M_BITMAPDATA->m_bitmapMask = mask ;
1508 }
1509
1510 WXHBITMAP wxBitmap::GetHBITMAP(WXHBITMAP* mask) const
1511 {
1512 wxUnusedVar(mask);
1513
1514 return WXHBITMAP(M_BITMAPDATA->GetBitmapContext());
1515 }
1516
1517 // ----------------------------------------------------------------------------
1518 // wxMask
1519 // ----------------------------------------------------------------------------
1520
1521 wxMask::wxMask()
1522 {
1523 Init() ;
1524 }
1525
1526 wxMask::wxMask(const wxMask &tocopy)
1527 {
1528 Init();
1529
1530 m_bytesPerRow = tocopy.m_bytesPerRow;
1531 m_width = tocopy.m_width;
1532 m_height = tocopy.m_height;
1533
1534 size_t size = m_bytesPerRow * m_height;
1535 unsigned char* dest = (unsigned char*)m_memBuf.GetWriteBuf( size );
1536 unsigned char* source = (unsigned char*)tocopy.m_memBuf.GetData();
1537 memcpy( dest, source, size );
1538 m_memBuf.UngetWriteBuf( size ) ;
1539 RealizeNative() ;
1540 }
1541
1542 // Construct a mask from a bitmap and a colour indicating
1543 // the transparent area
1544 wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
1545 {
1546 Init() ;
1547 Create( bitmap, colour );
1548 }
1549
1550 // Construct a mask from a mono bitmap (copies the bitmap).
1551 wxMask::wxMask( const wxBitmap& bitmap )
1552 {
1553 Init() ;
1554 Create( bitmap );
1555 }
1556
1557 // Construct a mask from a mono bitmap (copies the bitmap).
1558
1559 wxMask::wxMask( const wxMemoryBuffer& data, int width , int height , int bytesPerRow )
1560 {
1561 Init() ;
1562 Create( data, width , height , bytesPerRow );
1563 }
1564
1565 wxMask::~wxMask()
1566 {
1567 if ( m_maskBitmap )
1568 {
1569 CGContextRelease( (CGContextRef) m_maskBitmap );
1570 m_maskBitmap = NULL ;
1571 }
1572 }
1573
1574 void wxMask::Init()
1575 {
1576 m_width = m_height = m_bytesPerRow = 0 ;
1577 m_maskBitmap = NULL ;
1578 }
1579
1580 void *wxMask::GetRawAccess() const
1581 {
1582 return m_memBuf.GetData() ;
1583 }
1584
1585 // The default ColorTable for k8IndexedGrayPixelFormat in Intel appears to be broken, so we'll use an non-indexed
1586 // bitmap mask instead; in order to keep the code simple, the change applies to PowerPC implementations as well
1587
1588 void wxMask::RealizeNative()
1589 {
1590 if ( m_maskBitmap )
1591 {
1592 CGContextRelease( (CGContextRef) m_maskBitmap );
1593 m_maskBitmap = NULL ;
1594 }
1595
1596 CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
1597 // from MouseTracking sample :
1598 // Ironically, due to a bug in CGImageCreateWithMask, you cannot use
1599 // CGColorSpaceCreateWithName(kCGColorSpaceGenericGray) at this point!
1600
1601 m_maskBitmap = CGBitmapContextCreate((char*) m_memBuf.GetData(), m_width, m_height, 8, m_bytesPerRow, colorspace,
1602 kCGImageAlphaNone );
1603 CGColorSpaceRelease( colorspace );
1604 wxASSERT_MSG( m_maskBitmap , wxT("Unable to create CGBitmapContext context") ) ;
1605 }
1606
1607 // Create a mask from a mono bitmap (copies the bitmap).
1608
1609 bool wxMask::Create(const wxMemoryBuffer& data,int width , int height , int bytesPerRow)
1610 {
1611 m_memBuf = data ;
1612 m_width = width ;
1613 m_height = height ;
1614 m_bytesPerRow = bytesPerRow ;
1615
1616 wxASSERT( data.GetDataLen() == (size_t)(height * bytesPerRow) ) ;
1617
1618 RealizeNative() ;
1619
1620 return true ;
1621 }
1622
1623 // Create a mask from a mono bitmap (copies the bitmap).
1624 bool wxMask::Create(const wxBitmap& bitmap)
1625 {
1626 m_width = bitmap.GetWidth() ;
1627 m_height = bitmap.GetHeight() ;
1628 m_bytesPerRow = GetBestBytesPerRow( m_width * kMaskBytesPerPixel ) ;
1629
1630 size_t size = m_bytesPerRow * m_height ;
1631 unsigned char * destdatabase = (unsigned char*) m_memBuf.GetWriteBuf( size ) ;
1632 wxASSERT( destdatabase != NULL ) ;
1633
1634 memset( destdatabase , 0 , size ) ;
1635 unsigned char * srcdata = (unsigned char*) bitmap.GetRawAccess() ;
1636
1637 for ( int y = 0 ; y < m_height ; ++y , destdatabase += m_bytesPerRow )
1638 {
1639 unsigned char *destdata = destdatabase ;
1640 unsigned char r, g, b;
1641
1642 for ( int x = 0 ; x < m_width ; ++x )
1643 {
1644 srcdata++ ;
1645 r = *srcdata++ ;
1646 g = *srcdata++ ;
1647 b = *srcdata++ ;
1648
1649 if ( ( r + g + b ) > 0x10 )
1650 *destdata++ = 0xFF ;
1651 else
1652 *destdata++ = 0x00 ;
1653 }
1654 }
1655
1656 m_memBuf.UngetWriteBuf( size ) ;
1657 RealizeNative() ;
1658
1659 return true;
1660 }
1661
1662 // Create a mask from a bitmap and a colour indicating
1663 // the transparent area
1664 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
1665 {
1666 m_width = bitmap.GetWidth() ;
1667 m_height = bitmap.GetHeight() ;
1668 m_bytesPerRow = GetBestBytesPerRow( m_width * kMaskBytesPerPixel ) ;
1669
1670 size_t size = m_bytesPerRow * m_height ;
1671 unsigned char * destdatabase = (unsigned char*) m_memBuf.GetWriteBuf( size ) ;
1672 wxASSERT( destdatabase != NULL ) ;
1673
1674 memset( destdatabase , 0 , size ) ;
1675 unsigned char * srcdatabase = (unsigned char*) bitmap.GetRawAccess() ;
1676 size_t sourceBytesRow = bitmap.GetBitmapData()->GetBytesPerRow();
1677
1678 for ( int y = 0 ; y < m_height ; ++y , srcdatabase+= sourceBytesRow, destdatabase += m_bytesPerRow)
1679 {
1680 unsigned char *srcdata = srcdatabase ;
1681 unsigned char *destdata = destdatabase ;
1682 unsigned char r, g, b;
1683
1684 for ( int x = 0 ; x < m_width ; ++x )
1685 {
1686 srcdata++ ;
1687 r = *srcdata++ ;
1688 g = *srcdata++ ;
1689 b = *srcdata++ ;
1690
1691 if ( colour == wxColour( r , g , b ) )
1692 *destdata++ = 0xFF ;
1693 else
1694 *destdata++ = 0x00 ;
1695 }
1696 }
1697
1698 m_memBuf.UngetWriteBuf( size ) ;
1699 RealizeNative() ;
1700
1701 return true;
1702 }
1703
1704 WXHBITMAP wxMask::GetHBITMAP() const
1705 {
1706 return m_maskBitmap ;
1707 }
1708
1709 // ----------------------------------------------------------------------------
1710 // Standard Handlers
1711 // ----------------------------------------------------------------------------
1712
1713 class WXDLLEXPORT wxBundleResourceHandler: public wxBitmapHandler
1714 {
1715 DECLARE_ABSTRACT_CLASS(wxPNGResourceHandler)
1716
1717 public:
1718 inline wxBundleResourceHandler()
1719 {
1720 };
1721
1722 virtual bool LoadFile(wxBitmap *bitmap,
1723 const wxString& name,
1724 wxBitmapType type,
1725 int desiredWidth,
1726 int desiredHeight);
1727 };
1728
1729 IMPLEMENT_ABSTRACT_CLASS(wxBundleResourceHandler, wxBitmapHandler);
1730
1731 class WXDLLEXPORT wxPNGResourceHandler: public wxBundleResourceHandler
1732 {
1733 DECLARE_DYNAMIC_CLASS(wxPNGResourceHandler)
1734
1735 public:
1736 inline wxPNGResourceHandler()
1737 {
1738 SetName(wxT("PNG resource"));
1739 SetExtension("PNG");
1740 SetType(wxBITMAP_TYPE_PNG_RESOURCE);
1741 };
1742 };
1743
1744 IMPLEMENT_DYNAMIC_CLASS(wxPNGResourceHandler, wxBundleResourceHandler)
1745
1746 class WXDLLEXPORT wxJPEGResourceHandler: public wxBundleResourceHandler
1747 {
1748 DECLARE_DYNAMIC_CLASS(wxPNGResourceHandler)
1749
1750 public:
1751 inline wxJPEGResourceHandler()
1752 {
1753 SetName(wxT("JPEG resource"));
1754 SetExtension("JPEG");
1755 SetType(wxBITMAP_TYPE_JPEG_RESOURCE);
1756 };
1757 };
1758
1759 IMPLEMENT_DYNAMIC_CLASS(wxJPEGResourceHandler, wxBundleResourceHandler)
1760
1761 bool wxBundleResourceHandler::LoadFile(wxBitmap *bitmap,
1762 const wxString& name,
1763 wxBitmapType WXUNUSED(type),
1764 int WXUNUSED(desiredWidth),
1765 int WXUNUSED(desiredHeight))
1766 {
1767 wxString ext = GetExtension().Lower();
1768 wxCFStringRef resname(name);
1769 wxCFStringRef restype(ext);
1770
1771 wxCFRef<CFURLRef> imageURL(CFBundleCopyResourceURL(CFBundleGetMainBundle(), resname, restype, NULL));
1772
1773 if ( imageURL.get() != NULL )
1774 {
1775 // Create the data provider object
1776 wxCFRef<CGDataProviderRef> provider(CGDataProviderCreateWithURL (imageURL) );
1777 CGImageRef image = NULL;
1778
1779 if ( ext == "jpeg" )
1780 image = CGImageCreateWithJPEGDataProvider (provider, NULL, true,
1781 kCGRenderingIntentDefault);
1782 else if ( ext == "png" )
1783 image = CGImageCreateWithPNGDataProvider (provider, NULL, true,
1784 kCGRenderingIntentDefault);
1785 if ( image != NULL )
1786 {
1787 bitmap->Create(image);
1788 CGImageRelease(image);
1789 }
1790 }
1791
1792 return false ;
1793 }
1794
1795 #if !defined( __LP64__ ) && !defined(__WXOSX_IPHONE__)
1796
1797 class WXDLLEXPORT wxPICTResourceHandler: public wxBitmapHandler
1798 {
1799 DECLARE_DYNAMIC_CLASS(wxPICTResourceHandler)
1800
1801 public:
1802 inline wxPICTResourceHandler()
1803 {
1804 SetName(wxT("Macintosh Pict resource"));
1805 SetExtension(wxEmptyString);
1806 SetType(wxBITMAP_TYPE_PICT_RESOURCE);
1807 };
1808
1809 virtual bool LoadFile(wxBitmap *bitmap,
1810 const wxString& name,
1811 wxBitmapType type,
1812 int desiredWidth,
1813 int desiredHeight);
1814 };
1815
1816 IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler)
1817
1818
1819 bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap,
1820 const wxString& name,
1821 wxBitmapType WXUNUSED(type),
1822 int WXUNUSED(desiredWidth),
1823 int WXUNUSED(desiredHeight))
1824 {
1825 #if wxUSE_METAFILE
1826 Str255 theName ;
1827 wxMacStringToPascal( name , theName ) ;
1828
1829 PicHandle thePict = (PicHandle ) GetNamedResource( 'PICT' , theName ) ;
1830 if ( thePict )
1831 {
1832 wxMetafile mf ;
1833
1834 mf.SetPICT( thePict ) ;
1835 bitmap->Create( mf.GetWidth() , mf.GetHeight() ) ;
1836 wxMemoryDC dc ;
1837 dc.SelectObject( *bitmap ) ;
1838 mf.Play( &dc ) ;
1839 dc.SelectObject( wxNullBitmap ) ;
1840
1841 return true ;
1842 }
1843 #endif
1844
1845 return false ;
1846 }
1847 #endif
1848
1849 void wxBitmap::InitStandardHandlers()
1850 {
1851 #if !defined( __LP64__ ) && !defined(__WXOSX_IPHONE__)
1852 AddHandler( new wxPICTResourceHandler ) ;
1853 #endif
1854 #if wxOSX_USE_COCOA_OR_CARBON
1855 AddHandler( new wxICONResourceHandler ) ;
1856 #endif
1857 AddHandler( new wxPNGResourceHandler );
1858 AddHandler( new wxJPEGResourceHandler );
1859 }
1860
1861 // ----------------------------------------------------------------------------
1862 // raw bitmap access support
1863 // ----------------------------------------------------------------------------
1864
1865 void *wxBitmap::GetRawData(wxPixelDataBase& data, int WXUNUSED(bpp))
1866 {
1867 if ( !Ok() )
1868 // no bitmap, no data (raw or otherwise)
1869 return NULL;
1870
1871 data.m_width = GetWidth() ;
1872 data.m_height = GetHeight() ;
1873 data.m_stride = GetBitmapData()->GetBytesPerRow() ;
1874
1875 return BeginRawAccess() ;
1876 }
1877
1878 void wxBitmap::UngetRawData(wxPixelDataBase& WXUNUSED(dataBase))
1879 {
1880 EndRawAccess() ;
1881 }
1882
1883 void wxBitmap::UseAlpha()
1884 {
1885 // remember that we are using alpha channel:
1886 // we'll need to create a proper mask in UngetRawData()
1887 M_BITMAPDATA->UseAlpha( true );
1888 }