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