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