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