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