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