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