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