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