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