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