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