]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/bitmap.cpp
Added extra MicroWindows functions
[wxWidgets.git] / src / mac / carbon / bitmap.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: bitmap.cpp
3// Purpose: wxBitmap
4// Author: AUTHOR
5// Modified by:
6// Created: ??/??/98
7// RCS-ID: $Id$
8// Copyright: (c) AUTHOR
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "bitmap.h"
14#endif
15
03e11df5 16#include "wx/wx.h"
e9576ca5
SC
17#include "wx/setup.h"
18#include "wx/utils.h"
19#include "wx/palette.h"
20#include "wx/bitmap.h"
21#include "wx/icon.h"
22#include "wx/log.h"
fec19ea9 23#include "wx/image.h"
973b0afb 24#include "wx/xpmdecod.h"
e9576ca5 25
2f1ae414 26#if !USE_SHARED_LIBRARIES
e9576ca5
SC
27IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
28IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
2f1ae414 29#endif
e9576ca5 30
03e11df5 31#ifdef __UNIX__
5fde6fcc 32 #include <ApplicationServices/ApplicationServices.h>
03e11df5
GD
33#else
34 #include <PictUtils.h>
35#endif
519cb848 36
31d30995
SC
37#include "wx/mac/uma.h"
38
519cb848
SC
39CTabHandle wxMacCreateColorTable( int numColors )
40{
41 CTabHandle newColors; /* Handle to the new color table */
03e11df5 42
519cb848
SC
43 /* Allocate memory for the color table */
44 newColors = (CTabHandle)NewHandleClear( sizeof (ColorTable) +
45 sizeof (ColorSpec) * (numColors - 1) );
46 if (newColors != nil)
47 {
48 /* Initialize the fields */
49 (**newColors).ctSeed = GetCTSeed();
50 (**newColors).ctFlags = 0;
51 (**newColors).ctSize = numColors - 1;
52 /* Initialize the table of colors */
53 }
54 return newColors ;
55}
56
57void wxMacDestroyColorTable( CTabHandle colors )
58{
59 DisposeHandle( (Handle) colors ) ;
60}
61
62void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue )
63{
64 (**newColors).ctTable[index].value = index;
65 (**newColors).ctTable[index].rgb.red = 0 ;// someRedValue;
66 (**newColors).ctTable[index].rgb.green = 0 ; // someGreenValue;
67 (**newColors).ctTable[index].rgb.blue = 0 ; // someBlueValue;
68}
69
03e11df5 70GWorldPtr wxMacCreateGWorld( int width , int height , int depth )
519cb848
SC
71{
72 OSErr err = noErr ;
73 GWorldPtr port ;
03e11df5 74 Rect rect = { 0 , 0 , height , width } ;
519cb848
SC
75
76 if ( depth < 0 )
77 {
2f1ae414 78 depth = wxDisplayDepth() ;
519cb848
SC
79 }
80
81 err = NewGWorld( &port , depth , &rect , NULL , NULL , 0 ) ;
82 if ( err == noErr )
83 {
84 return port ;
85 }
86 return NULL ;
03e11df5 87}
519cb848
SC
88
89void wxMacDestroyGWorld( GWorldPtr gw )
90{
91 if ( gw )
92 DisposeGWorld( gw ) ;
93}
94
5fde6fcc
GD
95PicHandle wxMacCreatePict(GWorldPtr wp, GWorldPtr mask)
96{
97 CGrafPtr origPort ;
98 GDHandle origDev ;
99
100 PicHandle pict; // this is the Picture we give back
101
102 RGBColor gray = { 0xCCCC ,0xCCCC , 0xCCCC } ;
103 RGBColor white = { 0xffff ,0xffff , 0xffff } ;
104 RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ;
105
106 unsigned char *maskimage = NULL ;
107 Rect portRect ;
108 GetPortBounds( wp , &portRect ) ;
109 int width = portRect.right - portRect.left ;
110 int height = portRect.bottom - portRect.top ;
111
112 LockPixels( GetGWorldPixMap( wp ) ) ;
113 GetGWorld( &origPort , &origDev ) ;
114
115 if ( mask )
116 {
117 maskimage = (unsigned char*) malloc( width * height ) ;
118 SetGWorld( mask , NULL ) ;
119 LockPixels( GetGWorldPixMap( mask ) ) ;
120 for ( int y = 0 ; y < height ; y++ )
121 {
122 for( int x = 0 ; x < width ; x++ )
123 {
124 RGBColor col ;
125
126 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
127 maskimage[y*width + x] = ( col.red == 0 ) ; // for monochrome masks
128 }
129 }
130 UnlockPixels( GetGWorldPixMap( mask ) ) ;
131 }
132
133 SetGWorld( wp , NULL ) ;
134
135 pict = OpenPicture(&portRect); // open a picture, this disables drawing
136 if(!pict)
137 return NULL;
138
139 if ( maskimage )
140 {
141 RGBForeColor( &black ) ;
142 RGBBackColor( &white ) ;
143 PenMode(transparent);
144
145 for ( int y = 0 ; y < height ; ++y )
146 {
147 for( int x = 0 ; x < width ; ++x )
148 {
149 if ( maskimage[y*width + x] )
150 {
151 RGBColor col ;
152
153 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
154 SetCPixel( x + portRect.left , y + portRect.top , &col ) ;
155 }
156 else {
157 // With transparency set this sets a blank pixel not a white one
158 SetCPixel( x + portRect.left , y + portRect.top , &white);
159 }
160 }
161 }
162 free( maskimage ) ;
163 maskimage = NULL ;
164 }
165 else
166 {
167 RGBBackColor( &gray ) ;
168 EraseRect(&portRect);
169 RGBForeColor( &black ) ;
170 RGBBackColor( &white ) ;
171
172 CopyBits(GetPortBitMapForCopyBits(wp), /* src PixMap - we copy image over
173 * itself - */
174 GetPortBitMapForCopyBits(wp), // dst PixMap - no drawing occurs
175 &portRect, // srcRect - it will be recorded and compressed -
176 &portRect, // dstRect - into the picture that is open -
177 srcCopy,NULL); // copyMode and no clip region
178 }
179 ClosePicture(); // We are done recording the picture
180 UnlockPixels( GetGWorldPixMap( wp ) ) ;
181 SetGWorld( origPort , origDev ) ;
182
183 return pict; // return our groovy pict handle
184}
185
e9576ca5
SC
186wxBitmapRefData::wxBitmapRefData()
187{
188 m_ok = FALSE;
189 m_width = 0;
190 m_height = 0;
191 m_depth = 0;
192 m_quality = 0;
193 m_numColors = 0;
194 m_bitmapMask = NULL;
973b0afb
GD
195 m_hBitmap = NULL ;
196 m_hPict = NULL ;
3dec57ad 197 m_hIcon = NULL ;
973b0afb 198 m_bitmapType = kMacBitmapTypeUnknownType ;
e9576ca5
SC
199}
200
201wxBitmapRefData::~wxBitmapRefData()
202{
519cb848
SC
203 switch (m_bitmapType)
204 {
205 case kMacBitmapTypePict :
206 {
207 if ( m_hPict )
208 {
209 KillPicture( m_hPict ) ;
210 m_hPict = NULL ;
211 }
212 }
213 break ;
214 case kMacBitmapTypeGrafWorld :
215 {
216 if ( m_hBitmap )
217 {
218 wxMacDestroyGWorld( m_hBitmap ) ;
219 m_hBitmap = NULL ;
220 }
221 }
222 break ;
3dec57ad
SC
223 case kMacBitmapTypeIcon :
224 if ( m_hIcon )
225 {
226 DisposeCIcon( m_hIcon ) ;
227 m_hIcon = NULL ;
228 }
229
519cb848
SC
230 default :
231 // unkown type ?
232 break ;
03e11df5 233 }
519cb848
SC
234
235 if (m_bitmapMask)
236 {
237 delete m_bitmapMask;
e9576ca5 238 m_bitmapMask = NULL;
519cb848 239 }
e9576ca5
SC
240}
241
242wxList wxBitmap::sm_handlers;
243
244wxBitmap::wxBitmap()
245{
246 m_refData = NULL;
247
248 if ( wxTheBitmapList )
249 wxTheBitmapList->AddBitmap(this);
250}
251
252wxBitmap::~wxBitmap()
253{
254 if (wxTheBitmapList)
255 wxTheBitmapList->DeleteObject(this);
256}
257
258wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
259{
260 m_refData = new wxBitmapRefData;
261
262 M_BITMAPDATA->m_width = the_width ;
263 M_BITMAPDATA->m_height = the_height ;
264 M_BITMAPDATA->m_depth = no_bits ;
265 M_BITMAPDATA->m_numColors = 0;
d2c6d549
GD
266 if ( no_bits == 1 )
267 {
973b0afb
GD
268 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
269 M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( the_width , the_height , no_bits ) ;
270 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
519cb848 271
973b0afb
GD
272 CGrafPtr origPort ;
273 GDHandle origDevice ;
519cb848 274
973b0afb
GD
275 GetGWorld( &origPort , &origDevice ) ;
276 SetGWorld( M_BITMAPDATA->m_hBitmap , NULL ) ;
277 LockPixels( GetGWorldPixMap( M_BITMAPDATA->m_hBitmap ) ) ;
d2c6d549 278
973b0afb 279 // bits is a char array
d2c6d549 280
973b0afb
GD
281 unsigned char* linestart = (unsigned char*) bits ;
282 int linesize = ( the_width / (sizeof(unsigned char) * 8)) ;
283 if ( the_width % (sizeof(unsigned char) * 8) ) {
284 linesize += sizeof(unsigned char);
285 }
d2c6d549 286
973b0afb
GD
287 RGBColor colors[2] = {
288 { 0xFFFF , 0xFFFF , 0xFFFF } ,
289 { 0, 0 , 0 }
290 } ;
d2c6d549 291
973b0afb
GD
292 for ( int y = 0 ; y < the_height ; ++y , linestart += linesize )
293 {
294 for ( int x = 0 ; x < the_width ; ++x )
295 {
296 int index = x / 8 ;
297 int bit = x % 8 ;
298 int mask = 1 << bit ;
299 if ( linestart[index] & mask )
300 {
301 SetCPixel( x , y , &colors[1] ) ;
302 }
303 else
304 {
305 SetCPixel( x , y , &colors[0] ) ;
306 }
307 }
308 }
309 UnlockPixels( GetGWorldPixMap( M_BITMAPDATA->m_hBitmap ) ) ;
d2c6d549 310
973b0afb 311 SetGWorld( origPort , origDevice ) ;
d2c6d549
GD
312 }
313 else
314 {
973b0afb 315 wxFAIL_MSG(wxT("multicolor BITMAPs not yet implemented"));
d2c6d549
GD
316 }
317
318 if ( wxTheBitmapList ) {
e9576ca5 319 wxTheBitmapList->AddBitmap(this);
d2c6d549 320 }
e9576ca5
SC
321}
322
323wxBitmap::wxBitmap(int w, int h, int d)
324{
325 (void)Create(w, h, d);
326
327 if ( wxTheBitmapList )
328 wxTheBitmapList->AddBitmap(this);
329}
330
a8562f55 331wxBitmap::wxBitmap(void *data, wxBitmapType type, int width, int height, int depth)
e9576ca5
SC
332{
333 (void) Create(data, type, width, height, depth);
334
335 if ( wxTheBitmapList )
336 wxTheBitmapList->AddBitmap(this);
337}
338
a8562f55 339wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
e9576ca5 340{
a8562f55 341 LoadFile(filename, type);
e9576ca5
SC
342
343 if ( wxTheBitmapList )
344 wxTheBitmapList->AddBitmap(this);
345}
346
973b0afb 347bool wxBitmap::CreateFromXpm(const char **bits)
e9576ca5 348{
973b0afb
GD
349 wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") )
350 wxXPMDecoder decoder;
351 wxImage img = decoder.ReadData(bits);
352 wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid bitmap data") )
353 *this = wxBitmap(img);
354 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
355 return TRUE;
356}
357
358wxBitmap::wxBitmap(const char **bits)
359{
973b0afb 360 (void) CreateFromXpm(bits);
e9576ca5 361}
e9576ca5 362
973b0afb 363wxBitmap::wxBitmap(char **bits)
03e11df5 364{
973b0afb 365 (void) CreateFromXpm((const char **)bits);
03e11df5
GD
366}
367
5fde6fcc
GD
368wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const
369{
370 wxCHECK_MSG( Ok() &&
371 (rect.x >= 0) && (rect.y >= 0) &&
372 (rect.x+rect.width <= GetWidth()) &&
373 (rect.y+rect.height <= GetHeight()),
374 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
375
376
377 wxBitmap ret( rect.width, rect.height, GetDepth() );
378 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
379
380 WXHBITMAP origPort;
381 GDHandle origDevice;
382
383 GetGWorld( &origPort, &origDevice );
384
385 // Update the subbitmaps reference data
386 wxBitmapRefData *ref = (wxBitmapRefData *)ret.GetRefData();
387
388 ref->m_numColors = M_BITMAPDATA->m_numColors;
389 ref->m_bitmapPalette = M_BITMAPDATA->m_bitmapPalette;
390 ref->m_bitmapType = M_BITMAPDATA->m_bitmapType;
391
392 // Copy sub region of this bitmap
393 if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypePict)
394 {
395 printf("GetSubBitmap: Copy a region of a Pict structure - TODO\n");
396 }
397 else if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypeGrafWorld)
398 {
399 // Copy mask
400 if(GetMask())
401 {
402 WXHBITMAP submask, mask;
403 RGBColor color;
404
405 mask = GetMask()->GetMaskBitmap();
406 submask = wxMacCreateGWorld(rect.width, rect.height, 1);
407 LockPixels(GetGWorldPixMap(mask));
408 LockPixels(GetGWorldPixMap(submask));
409
410 for(int yy = 0; yy < rect.height; yy++)
411 {
412 for(int xx = 0; xx < rect.width; xx++)
413 {
414 SetGWorld(mask, NULL);
415 GetCPixel(rect.x + xx, rect.y + yy, &color);
416 SetGWorld(submask, NULL);
417 SetCPixel(xx,yy, &color);
418 }
419 }
420 UnlockPixels(GetGWorldPixMap(mask));
421 UnlockPixels(GetGWorldPixMap(submask));
422 ref->m_bitmapMask = new wxMask;
423 ref->m_bitmapMask->SetMaskBitmap(submask);
424 }
425
426 // Copy bitmap
427 if(GetHBITMAP())
428 {
429 WXHBITMAP subbitmap, bitmap;
430 RGBColor color;
431
432 bitmap = GetHBITMAP();
433 subbitmap = wxMacCreateGWorld(rect.width, rect.height, GetDepth());
434 LockPixels(GetGWorldPixMap(bitmap));
435 LockPixels(GetGWorldPixMap(subbitmap));
436
437 for(int yy = 0; yy < rect.height; yy++)
438 {
439 for(int xx = 0; xx < rect.width; xx++)
440 {
441 SetGWorld(bitmap, NULL);
442 GetCPixel(rect.x + xx, rect.y + yy, &color);
443 SetGWorld(subbitmap, NULL);
444 SetCPixel(xx, yy, &color);
445 }
446 }
447 UnlockPixels(GetGWorldPixMap(bitmap));
448 UnlockPixels(GetGWorldPixMap(subbitmap));
449 ret.SetHBITMAP(subbitmap);
450 }
451 }
452 SetGWorld( origPort, origDevice );
453
454 return ret;
455}
456
e9576ca5
SC
457bool wxBitmap::Create(int w, int h, int d)
458{
459 UnRef();
460
461 m_refData = new wxBitmapRefData;
462
463 M_BITMAPDATA->m_width = w;
464 M_BITMAPDATA->m_height = h;
465 M_BITMAPDATA->m_depth = d;
466
519cb848
SC
467 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
468 M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( w , h , d ) ;
a8562f55 469 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
e9576ca5
SC
470 return M_BITMAPDATA->m_ok;
471}
472
5fde6fcc
GD
473int wxBitmap::GetBitmapType() const
474{
475 wxCHECK_MSG( Ok(), kMacBitmapTypeUnknownType, wxT("invalid bitmap") );
476
477 return M_BITMAPDATA->m_bitmapType;
478}
479
519cb848
SC
480void wxBitmap::SetHBITMAP(WXHBITMAP bmp)
481{
482 M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
483 M_BITMAPDATA->m_hBitmap = bmp ;
3dec57ad 484 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
519cb848
SC
485}
486
a8562f55 487bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
e9576ca5
SC
488{
489 UnRef();
490
e9576ca5
SC
491 wxBitmapHandler *handler = FindHandler(type);
492
a8562f55
GD
493 if ( handler )
494 {
495 m_refData = new wxBitmapRefData;
e9576ca5 496
a8562f55 497 return handler->LoadFile(this, filename, type, -1, -1);
e9576ca5 498 }
a8562f55
GD
499 else
500 {
501 wxImage loadimage(filename, type);
502 if (loadimage.Ok()) {
503 *this = loadimage;
504 return true;
505 }
506 }
507 wxLogWarning("no bitmap handler for type %d defined.", type);
508 return false;
e9576ca5
SC
509}
510
a8562f55 511bool wxBitmap::Create(void *data, wxBitmapType type, int width, int height, int depth)
e9576ca5
SC
512{
513 UnRef();
514
515 m_refData = new wxBitmapRefData;
516
517 wxBitmapHandler *handler = FindHandler(type);
518
519 if ( handler == NULL ) {
520 wxLogWarning("no bitmap handler for type %d defined.", type);
521
522 return FALSE;
523 }
524
525 return handler->Create(this, data, type, width, height, depth);
526}
527
fec19ea9
VS
528wxBitmap::wxBitmap(const wxImage& image, int depth)
529{
530 wxCHECK_RET( image.Ok(), wxT("invalid image") )
531 wxCHECK_RET( depth == -1, wxT("invalid bitmap depth") )
532
533 m_refData = new wxBitmapRefData();
534
535 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
536
537 // width and height of the device-dependent bitmap
538 int width = image.GetWidth();
539 int height = image.GetHeight();
540
541 // Create picture
542
543 Create( width , height , wxDisplayDepth() ) ;
544 wxBitmap maskBitmap( width, height, 1);
545
546 CGrafPtr origPort ;
547 GDHandle origDevice ;
548
549 LockPixels( GetGWorldPixMap(GetHBITMAP()) );
550 LockPixels( GetGWorldPixMap(maskBitmap.GetHBITMAP()) );
551
552 GetGWorld( &origPort , &origDevice ) ;
553 SetGWorld( GetHBITMAP() , NULL ) ;
554
555 // Render image
556 wxColour rgb, maskcolor(image.GetMaskRed(), image.GetMaskGreen(), image.GetMaskBlue());
557 RGBColor color;
558 RGBColor white = { 0xffff, 0xffff, 0xffff };
559 RGBColor black = { 0 , 0 , 0 };
560
561 register unsigned char* data = image.GetData();
562
563 int index = 0;
564 for (int y = 0; y < height; y++)
565 {
566 for (int x = 0; x < width; x++)
567 {
568 rgb.Set(data[index++], data[index++], data[index++]);
569 color = rgb.GetPixel();
570 SetCPixel( x , y , &color ) ;
571 if (image.HasMask())
572 {
573 SetGWorld(maskBitmap.GetHBITMAP(), NULL);
574 if (rgb == maskcolor) {
575 SetCPixel(x,y, &white);
576 }
577 else {
578 SetCPixel(x,y, &black);
579 }
580 SetGWorld(GetHBITMAP(), NULL);
581 }
582 }
583 } // for height
584
585 // Create mask
586 if ( image.HasMask() ) {
4ce431b0 587 SetMask(new wxMask( maskBitmap ));
fec19ea9
VS
588 }
589
590 UnlockPixels( GetGWorldPixMap(GetHBITMAP()) );
591 UnlockPixels( GetGWorldPixMap(maskBitmap.GetHBITMAP()) );
592 SetGWorld( origPort, origDevice );
593}
594
595wxImage wxBitmap::ConvertToImage() const
596{
597 wxImage image;
598
599 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
600
601 // create an wxImage object
602 int width = GetWidth();
603 int height = GetHeight();
604 image.Create( width, height );
605
606 unsigned char *data = image.GetData();
607
608 wxCHECK_MSG( data, wxNullImage, wxT("Could not allocate data for image") );
609
610 WXHBITMAP origPort;
611 GDHandle origDevice;
612 int index;
613 RGBColor color;
614 // background color set to RGB(16,16,16) in consistent with wxGTK
615 unsigned char mask_r=16, mask_g=16, mask_b=16;
616 SInt16 r,g,b;
617 wxMask *mask = GetMask();
618
619 GetGWorld( &origPort, &origDevice );
620 LockPixels(GetGWorldPixMap(GetHBITMAP()));
621 SetGWorld( GetHBITMAP(), NULL);
622
623 // Copy data into image
624 index = 0;
625 for (int yy = 0; yy < height; yy++)
626 {
627 for (int xx = 0; xx < width; xx++)
628 {
629 GetCPixel(xx,yy, &color);
630 r = ((color.red ) >> 8);
631 g = ((color.green ) >> 8);
632 b = ((color.blue ) >> 8);
633 data[index ] = r;
634 data[index + 1] = g;
635 data[index + 2] = b;
636 if (mask)
637 {
638 if (mask->PointMasked(xx,yy))
639 {
640 data[index ] = mask_r;
641 data[index + 1] = mask_g;
642 data[index + 2] = mask_b;
643 }
644 }
645 index += 3;
646 }
647 }
648 if (mask)
649 {
650 image.SetMaskColour( mask_r, mask_g, mask_b );
651 image.SetMask( true );
652 }
653
654 // Free resources
655 UnlockPixels(GetGWorldPixMap(GetHBITMAP()));
656 SetGWorld(origPort, origDevice);
657
658 return image;
659}
660
661
a8562f55
GD
662bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type,
663 const wxPalette *palette) const
e9576ca5
SC
664{
665 wxBitmapHandler *handler = FindHandler(type);
666
a8562f55
GD
667 if ( handler )
668 {
669 return handler->SaveFile(this, filename, type, palette);
670 }
671 else
672 {
673 wxImage image = ConvertToImage();
e9576ca5 674
a8562f55
GD
675 return image.SaveFile(filename, type);
676 }
677
678 wxLogWarning("no bitmap handler for type %d defined.", type);
679 return false;
e9576ca5
SC
680}
681
5fde6fcc
GD
682bool wxBitmap::Ok() const
683{
684 return (M_BITMAPDATA && M_BITMAPDATA->m_ok);
685}
686
687int wxBitmap::GetHeight() const
688{
689 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
690
691 return M_BITMAPDATA->m_height;
692}
693
694int wxBitmap::GetWidth() const
695{
696 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
697
698 return M_BITMAPDATA->m_width;
699}
700
701int wxBitmap::GetDepth() const
702{
703 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
704
705 return M_BITMAPDATA->m_depth;
706}
707
708int wxBitmap::GetQuality() const
709{
710 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
711
712 return M_BITMAPDATA->m_quality;
713}
714
715wxMask *wxBitmap::GetMask() const
716{
717 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
718
719 return M_BITMAPDATA->m_bitmapMask;
720}
721
e9576ca5
SC
722void wxBitmap::SetWidth(int w)
723{
724 if (!M_BITMAPDATA)
725 m_refData = new wxBitmapRefData;
726
727 M_BITMAPDATA->m_width = w;
728}
729
730void wxBitmap::SetHeight(int h)
731{
732 if (!M_BITMAPDATA)
733 m_refData = new wxBitmapRefData;
734
735 M_BITMAPDATA->m_height = h;
736}
737
738void wxBitmap::SetDepth(int d)
739{
740 if (!M_BITMAPDATA)
741 m_refData = new wxBitmapRefData;
742
743 M_BITMAPDATA->m_depth = d;
744}
745
746void wxBitmap::SetQuality(int q)
747{
748 if (!M_BITMAPDATA)
749 m_refData = new wxBitmapRefData;
750
751 M_BITMAPDATA->m_quality = q;
752}
753
754void wxBitmap::SetOk(bool isOk)
755{
756 if (!M_BITMAPDATA)
757 m_refData = new wxBitmapRefData;
758
759 M_BITMAPDATA->m_ok = isOk;
760}
761
5fde6fcc
GD
762wxPalette *wxBitmap::GetPalette() const
763{
764 wxCHECK_MSG( Ok(), NULL, wxT("Invalid bitmap GetPalette()") );
765
766 return &M_BITMAPDATA->m_bitmapPalette;
767}
768
e9576ca5
SC
769void wxBitmap::SetPalette(const wxPalette& palette)
770{
771 if (!M_BITMAPDATA)
772 m_refData = new wxBitmapRefData;
773
774 M_BITMAPDATA->m_bitmapPalette = palette ;
775}
776
777void wxBitmap::SetMask(wxMask *mask)
778{
779 if (!M_BITMAPDATA)
780 m_refData = new wxBitmapRefData;
781
a8562f55
GD
782 // Remove existing mask if there is one.
783 if (M_BITMAPDATA->m_bitmapMask)
784 delete M_BITMAPDATA->m_bitmapMask;
785
e9576ca5
SC
786 M_BITMAPDATA->m_bitmapMask = mask ;
787}
788
5fde6fcc
GD
789WXHBITMAP wxBitmap::GetHBITMAP() const
790{
791 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
792
793 return M_BITMAPDATA->m_hBitmap;
794}
795
796PicHandle wxBitmap::GetPict() const
797{
798 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
799
800 PicHandle picture; // This is the returned picture
801
802 // If bitmap already in Pict format return pointer
803 if(M_BITMAPDATA->m_bitmapType == kMacBitmapTypePict) {
804 return M_BITMAPDATA->m_hPict;
805 }
806 else if(M_BITMAPDATA->m_bitmapType != kMacBitmapTypeGrafWorld) {
807 // Invalid bitmap
808 return NULL;
809 }
810
811 RGBColor gray = { 0xCCCC ,0xCCCC , 0xCCCC } ;
812 RGBColor white = { 0xffff ,0xffff , 0xffff } ;
813 RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ;
814 CGrafPtr origPort;
815 GDHandle origDev ;
816 wxMask *mask;
817 Rect portRect ;
818
819 GetPortBounds( GetHBITMAP() , &portRect ) ;
820 int width = portRect.right - portRect.left ;
821 int height = portRect.bottom - portRect.top ;
822
823 LockPixels( GetGWorldPixMap( GetHBITMAP() ) ) ;
824 GetGWorld( &origPort , &origDev ) ;
825
826 mask = GetMask();
827
828 SetGWorld( GetHBITMAP() , NULL ) ;
829
830 picture = OpenPicture(&portRect); // open a picture, this disables drawing
831 if(!picture) {
832 return NULL;
833 }
834
835 if( mask )
836 {
837#ifdef __UNIX__
838 RGBColor trans = white;
839#else
840 RGBBackColor( &gray );
841 EraseRect( &portRect );
842 RGBColor trans = gray;
843#endif
844 RGBForeColor( &black ) ;
845 RGBBackColor( &white ) ;
846 PenMode(transparent);
847
848 for ( int y = 0 ; y < height ; ++y )
849 {
850 for( int x = 0 ; x < width ; ++x )
851 {
852 if ( !mask->PointMasked(x,y) )
853 {
854 RGBColor col ;
855
856 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
857 SetCPixel( x + portRect.left , y + portRect.top , &col ) ;
858 }
859 else {
860 // With transparency this sets a blank pixel
861 SetCPixel( x + portRect.left , y + portRect.top , &trans);
862 }
863 }
864 }
865 }
866 else
867 {
868 RGBBackColor( &gray ) ;
869 EraseRect(&portRect);
870 RGBForeColor( &black ) ;
871 RGBBackColor( &white ) ;
872
873 CopyBits(GetPortBitMapForCopyBits(GetHBITMAP()),
874 // src PixMap - we copy image over itself -
875 GetPortBitMapForCopyBits(GetHBITMAP()),
876 // dst PixMap - no drawing occurs
877 &portRect, // srcRect - it will be recorded and compressed -
878 &portRect, // dstRect - into the picture that is open -
879 srcCopy,NULL); // copyMode and no clip region
880 }
881 ClosePicture(); // We are done recording the picture
882 UnlockPixels( GetGWorldPixMap( GetHBITMAP() ) ) ;
883 SetGWorld( origPort , origDev ) ;
884
885 return picture; // return our groovy pict handle
886}
887
e9576ca5
SC
888void wxBitmap::AddHandler(wxBitmapHandler *handler)
889{
890 sm_handlers.Append(handler);
891}
892
893void wxBitmap::InsertHandler(wxBitmapHandler *handler)
894{
895 sm_handlers.Insert(handler);
896}
897
898bool wxBitmap::RemoveHandler(const wxString& name)
899{
900 wxBitmapHandler *handler = FindHandler(name);
901 if ( handler )
902 {
903 sm_handlers.DeleteObject(handler);
904 return TRUE;
905 }
906 else
907 return FALSE;
908}
909
910wxBitmapHandler *wxBitmap::FindHandler(const wxString& name)
911{
912 wxNode *node = sm_handlers.First();
913 while ( node )
914 {
915 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
916 if ( handler->GetName() == name )
917 return handler;
918 node = node->Next();
919 }
920 return NULL;
921}
922
a8562f55 923wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, wxBitmapType type)
e9576ca5
SC
924{
925 wxNode *node = sm_handlers.First();
926 while ( node )
927 {
928 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
929 if ( handler->GetExtension() == extension &&
a8562f55 930 (type == -1 || handler->GetType() == type) )
e9576ca5
SC
931 return handler;
932 node = node->Next();
933 }
934 return NULL;
935}
936
a8562f55 937wxBitmapHandler *wxBitmap::FindHandler(wxBitmapType type)
e9576ca5
SC
938{
939 wxNode *node = sm_handlers.First();
940 while ( node )
941 {
942 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
a8562f55 943 if (handler->GetType() == type)
e9576ca5
SC
944 return handler;
945 node = node->Next();
946 }
947 return NULL;
948}
949
950/*
951 * wxMask
952 */
953
954wxMask::wxMask()
955{
e9576ca5 956 m_maskBitmap = 0;
e9576ca5
SC
957}
958
959// Construct a mask from a bitmap and a colour indicating
960// the transparent area
961wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
962{
e9576ca5 963 m_maskBitmap = 0;
e9576ca5
SC
964 Create(bitmap, colour);
965}
966
967// Construct a mask from a bitmap and a palette index indicating
968// the transparent area
969wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
970{
e9576ca5 971 m_maskBitmap = 0;
e9576ca5
SC
972 Create(bitmap, paletteIndex);
973}
974
975// Construct a mask from a mono bitmap (copies the bitmap).
976wxMask::wxMask(const wxBitmap& bitmap)
977{
e9576ca5 978 m_maskBitmap = 0;
e9576ca5
SC
979 Create(bitmap);
980}
981
982wxMask::~wxMask()
983{
8208e181
SC
984 if ( m_maskBitmap )
985 {
986 wxMacDestroyGWorld( m_maskBitmap ) ;
987 m_maskBitmap = NULL ;
988 }
e9576ca5
SC
989}
990
991// Create a mask from a mono bitmap (copies the bitmap).
992bool wxMask::Create(const wxBitmap& bitmap)
993{
5fde6fcc
GD
994 if ( m_maskBitmap )
995 {
996 wxMacDestroyGWorld( m_maskBitmap ) ;
997 m_maskBitmap = NULL ;
998 }
999 wxCHECK_MSG( bitmap.GetBitmapType() == kMacBitmapTypeGrafWorld, false,
1000 wxT("Cannot create mask from this bitmap type (TODO)"));
1001 // other types would require a temporary bitmap. not yet implemented
1002
1003 wxCHECK_MSG( bitmap.Ok(), false, wxT("Invalid bitmap"));
1004
1005 wxCHECK_MSG(bitmap.GetDepth() == 1, false,
1006 wxT("Cannot create mask from colour bitmap"));
1007
1008 m_maskBitmap = wxMacCreateGWorld(bitmap.GetWidth(), bitmap.GetHeight(), 1);
1009 Rect rect = { 0,0, bitmap.GetHeight(), bitmap.GetWidth() };
1010
1011 LockPixels( GetGWorldPixMap(m_maskBitmap) );
1012 LockPixels( GetGWorldPixMap(bitmap.GetHBITMAP()) );
1013 CopyBits(GetPortBitMapForCopyBits(bitmap.GetHBITMAP()),
1014 GetPortBitMapForCopyBits(m_maskBitmap),
1015 &rect, &rect, srcCopy, 0);
1016 UnlockPixels( GetGWorldPixMap(m_maskBitmap) );
1017 UnlockPixels( GetGWorldPixMap(bitmap.GetHBITMAP()) );
1018
1019 return FALSE;
e9576ca5
SC
1020}
1021
1022// Create a mask from a bitmap and a palette index indicating
1023// the transparent area
1024bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
1025{
1026// TODO
5fde6fcc 1027 wxCHECK_MSG( 0, false, wxT("Not implemented"));
e9576ca5
SC
1028 return FALSE;
1029}
1030
1031// Create a mask from a bitmap and a colour indicating
1032// the transparent area
1033bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
1034{
8208e181
SC
1035 if ( m_maskBitmap )
1036 {
1037 wxMacDestroyGWorld( m_maskBitmap ) ;
1038 m_maskBitmap = NULL ;
1039 }
5fde6fcc
GD
1040 wxCHECK_MSG( bitmap.GetBitmapType() == kMacBitmapTypeGrafWorld, false,
1041 wxT("Cannot create mask from this bitmap type (TODO)"));
8208e181
SC
1042 // other types would require a temporary bitmap. not yet implemented
1043
5fde6fcc 1044 wxCHECK_MSG( bitmap.Ok(), false, wxT("Illigal bitmap"));
8208e181 1045
5fde6fcc
GD
1046 m_maskBitmap = wxMacCreateGWorld( bitmap.GetWidth() , bitmap.GetHeight() , 1 );
1047 LockPixels( GetGWorldPixMap( m_maskBitmap ) );
1048 LockPixels( GetGWorldPixMap( bitmap.GetHBITMAP() ) );
1049 RGBColor maskColor = colour.GetPixel();
8208e181
SC
1050
1051 // this is not very efficient, but I can't think
1052 // of a better way of doing it
1053 CGrafPtr origPort ;
1054 GDHandle origDevice ;
5fde6fcc
GD
1055 RGBColor col;
1056 RGBColor colors[2] = {
1057 { 0xFFFF, 0xFFFF, 0xFFFF },
1058 { 0, 0, 0 }};
8208e181
SC
1059
1060 GetGWorld( &origPort , &origDevice ) ;
1061 for (int w = 0; w < bitmap.GetWidth(); w++)
1062 {
1063 for (int h = 0; h < bitmap.GetHeight(); h++)
1064 {
5fde6fcc 1065 SetGWorld( bitmap.GetHBITMAP(), NULL ) ;
8208e181
SC
1066 GetCPixel( w , h , &col ) ;
1067 SetGWorld( m_maskBitmap , NULL ) ;
5fde6fcc 1068 if (col.red == maskColor.red && col.green == maskColor.green && col.blue == maskColor.blue)
8208e181
SC
1069 {
1070 SetCPixel( w , h , &colors[0] ) ;
1071 }
1072 else
1073 {
1074 SetCPixel( w , h , &colors[1] ) ;
1075 }
1076 }
1077 }
2f1ae414 1078 UnlockPixels( GetGWorldPixMap( (CGrafPtr) m_maskBitmap ) ) ;
5fde6fcc 1079 UnlockPixels( GetGWorldPixMap( bitmap.GetHBITMAP() ) ) ;
8208e181
SC
1080 SetGWorld( origPort , origDevice ) ;
1081
1082 return TRUE;
e9576ca5
SC
1083}
1084
5fde6fcc
GD
1085bool wxMask::PointMasked(int x, int y)
1086{
1087 WXHBITMAP origPort;
1088 GDHandle origDevice;
1089 RGBColor color;
1090 bool masked = true;
1091
1092 GetGWorld( &origPort, &origDevice);
1093
1094 //Set port to mask and see if it masked (1) or not ( 0 )
1095 SetGWorld(m_maskBitmap, NULL);
1096 LockPixels(GetGWorldPixMap(m_maskBitmap));
1097 GetCPixel(x,y, &color);
1098 masked = !(color.red == 0 && color.green == 0 && color.blue == 0);
1099 UnlockPixels(GetGWorldPixMap(m_maskBitmap));
1100
1101 SetGWorld( origPort, origDevice);
1102
1103 return masked;
1104}
1105
e9576ca5
SC
1106/*
1107 * wxBitmapHandler
1108 */
1109
1110IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
1111
1112bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth)
1113{
1114 return FALSE;
1115}
1116
a8562f55 1117bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
e9576ca5
SC
1118 int desiredWidth, int desiredHeight)
1119{
1120 return FALSE;
1121}
1122
a8562f55 1123bool wxBitmapHandler::SaveFile(const wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
e9576ca5
SC
1124{
1125 return FALSE;
1126}
1127
1128/*
1129 * Standard handlers
1130 */
1131
519cb848
SC
1132class WXDLLEXPORT wxPICTResourceHandler: public wxBitmapHandler
1133{
1134 DECLARE_DYNAMIC_CLASS(wxPICTResourceHandler)
1135public:
1136 inline wxPICTResourceHandler()
1137 {
1138 m_name = "Macintosh Pict resource";
1139 m_extension = "";
1140 m_type = wxBITMAP_TYPE_PICT_RESOURCE;
1141 };
1142
1143 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1144 int desiredWidth, int desiredHeight);
1145};
1146IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler)
1147
1148bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1149 int desiredWidth, int desiredHeight)
1150{
1151 Str255 theName ;
1152
03e11df5
GD
1153#if TARGET_CARBON
1154 c2pstrcpy( (StringPtr) theName , name ) ;
1155#else
1156 strcpy( (char *) theName , name ) ;
1157 c2pstr( (char *)theName ) ;
1158#endif
519cb848
SC
1159
1160 PicHandle thePict = (PicHandle ) GetNamedResource( 'PICT' , theName ) ;
1161 if ( thePict )
1162 {
1163 PictInfo theInfo ;
1164
1165 GetPictInfo( thePict , &theInfo , 0 , 0 , systemMethod , 0 ) ;
1166 DetachResource( (Handle) thePict ) ;
1167 M_BITMAPHANDLERDATA->m_bitmapType = kMacBitmapTypePict ;
1168 M_BITMAPHANDLERDATA->m_hPict = thePict ;
1169 M_BITMAPHANDLERDATA->m_width = theInfo.sourceRect.right - theInfo.sourceRect.left ;
1170 M_BITMAPHANDLERDATA->m_height = theInfo.sourceRect.bottom - theInfo.sourceRect.top ;
1171
1172 M_BITMAPHANDLERDATA->m_depth = theInfo.depth ;
1173 M_BITMAPHANDLERDATA->m_ok = true ;
1174 M_BITMAPHANDLERDATA->m_numColors = theInfo.uniqueColors ;
1175// M_BITMAPHANDLERDATA->m_bitmapPalette;
1176// M_BITMAPHANDLERDATA->m_quality;
1177 return TRUE ;
1178 }
1179 return FALSE ;
1180}
1181
a8562f55 1182#if 0 // The following is an example for creating a bitmap handler
519cb848 1183
a8562f55 1184// TODO: bitmap handlers, a bit like this:
519cb848
SC
1185class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
1186{
1187 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
1188public:
1189 inline wxBMPResourceHandler()
1190 {
1191 m_name = "Windows bitmap resource";
1192 m_extension = "";
1193 m_type = wxBITMAP_TYPE_BMP_RESOURCE;
1194 };
1195
1196 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
1197 int desiredWidth, int desiredHeight);
1198};
519cb848
SC
1199IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
1200
519cb848 1201#endif
519cb848 1202
e9576ca5
SC
1203void wxBitmap::CleanUpHandlers()
1204{
1205 wxNode *node = sm_handlers.First();
1206 while ( node )
1207 {
1208 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
1209 wxNode *next = node->Next();
1210 delete handler;
1211 delete node;
1212 node = next;
1213 }
1214}
1215
1216void wxBitmap::InitStandardHandlers()
1217{
973b0afb
GD
1218 AddHandler(new wxPICTResourceHandler) ;
1219 AddHandler(new wxICONResourceHandler) ;
e9576ca5 1220}