wxCocoa: Added preliminary wxBitmap support
[wxWidgets.git] / src / cocoa / bitmap.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/bitmap.cpp
3 // Purpose:     wxBitmap
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2003/07/19
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2003 David Elliott
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/setup.h"
13 #include "wx/utils.h"
14 #include "wx/palette.h"
15 #include "wx/bitmap.h"
16 #include "wx/icon.h"
17 #include "wx/log.h"
18 #include "wx/image.h"
19 #include "wx/xpmdecod.h"
20
21 #include "wx/cocoa/autorelease.h"
22 #include "wx/cocoa/string.h"
23
24 #import <AppKit/NSBitmapImageRep.h>
25 #import <AppKit/NSGraphics.h>
26
27 // ========================================================================
28 // wxBitmapRefData
29 // ========================================================================
30 class wxBitmapRefData: public wxGDIRefData
31 {
32     friend class wxBitmap;
33 public:
34     wxBitmapRefData();
35     wxBitmapRefData( const wxBitmapRefData& data );
36     virtual ~wxBitmapRefData();
37
38 protected:
39     int                 m_width;
40     int                 m_height;
41     int                 m_depth;
42     bool                m_ok;
43     int                 m_numColors;
44     wxPalette           m_bitmapPalette;
45     int                 m_quality;
46     WX_NSBitmapImageRep m_cocoaNSBitmapImageRep;
47     wxMask             *m_bitmapMask; // Optional mask
48 };
49
50 #define M_BITMAPDATA ((wxBitmapRefData *)m_refData)
51
52 wxBitmapRefData::wxBitmapRefData()
53 {
54     m_ok = FALSE;
55     m_width = 0;
56     m_height = 0;
57     m_depth = 0;
58     m_quality = 0;
59     m_numColors = 0;
60     m_cocoaNSBitmapImageRep = nil;
61     m_bitmapMask = NULL;
62 }
63
64 wxBitmapRefData::wxBitmapRefData( const wxBitmapRefData& data)
65 {
66     m_width = data.m_width;
67     m_height = data.m_height;
68     m_depth = data.m_depth;
69     m_ok = data.m_ok;
70     m_numColors = data.m_numColors;
71     m_bitmapPalette = data.m_bitmapPalette;
72     m_quality = data.m_quality;
73     m_cocoaNSBitmapImageRep = data.m_cocoaNSBitmapImageRep;
74     [m_cocoaNSBitmapImageRep retain];
75     m_bitmapMask = data.m_bitmapMask?new wxMask(*data.m_bitmapMask):NULL;
76 }
77
78 wxBitmapRefData::~wxBitmapRefData()
79 {
80     [m_cocoaNSBitmapImageRep release];
81     m_cocoaNSBitmapImageRep = NULL;
82
83     delete m_bitmapMask;
84     m_bitmapMask = NULL;
85 }
86
87 // ========================================================================
88 // wxBitmap
89 // ========================================================================
90 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
91
92 wxBitmap::wxBitmap()
93 {
94     m_refData = NULL;
95
96     if ( wxTheBitmapList )
97         wxTheBitmapList->AddBitmap(this);
98 }
99
100 wxBitmap::~wxBitmap()
101 {
102     if (wxTheBitmapList)
103         wxTheBitmapList->DeleteObject(this);
104 }
105
106 wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
107 {
108     m_refData = new wxBitmapRefData;
109
110     M_BITMAPDATA->m_width = the_width ;
111     M_BITMAPDATA->m_height = the_height ;
112     M_BITMAPDATA->m_depth = no_bits ;
113     M_BITMAPDATA->m_numColors = 0;
114
115     /* TODO: create the bitmap from data */
116
117     if ( wxTheBitmapList )
118         wxTheBitmapList->AddBitmap(this);
119 }
120
121 wxBitmap::wxBitmap(int w, int h, int d)
122 {
123     (void)Create(w, h, d);
124
125     if ( wxTheBitmapList )
126         wxTheBitmapList->AddBitmap(this);
127 }
128
129 wxBitmap::wxBitmap(void *data, wxBitmapType type, int width, int height, int depth)
130 {
131     (void) Create(data, type, width, height, depth);
132
133     if ( wxTheBitmapList )
134         wxTheBitmapList->AddBitmap(this);
135 }
136
137 wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
138 {
139     LoadFile(filename, type);
140
141     if ( wxTheBitmapList )
142         wxTheBitmapList->AddBitmap(this);
143 }
144
145 wxObjectRefData *wxBitmap::CreateRefData() const
146 {
147     return new wxBitmapRefData;
148 }
149
150 wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *data) const
151 {
152     return new wxBitmapRefData(*(wxBitmapRefData*)data);
153 }
154
155 WX_NSBitmapImageRep wxBitmap::GetNSBitmapImageRep()
156 {
157     if(!M_BITMAPDATA)
158         return NULL;
159     return M_BITMAPDATA->m_cocoaNSBitmapImageRep;
160 }
161
162 void wxBitmap::SetWidth(int w)
163 {
164     if (!M_BITMAPDATA)
165         m_refData = new wxBitmapRefData;
166
167     M_BITMAPDATA->m_width = w;
168 }
169
170 void wxBitmap::SetHeight(int h)
171 {
172     if (!M_BITMAPDATA)
173         m_refData = new wxBitmapRefData;
174
175     M_BITMAPDATA->m_height = h;
176 }
177
178 void wxBitmap::SetDepth(int d)
179 {
180     if (!M_BITMAPDATA)
181         m_refData = new wxBitmapRefData;
182
183     M_BITMAPDATA->m_depth = d;
184 }
185
186 void wxBitmap::SetQuality(int q)
187 {
188     if (!M_BITMAPDATA)
189         m_refData = new wxBitmapRefData;
190
191     M_BITMAPDATA->m_quality = q;
192 }
193
194 void wxBitmap::SetOk(bool isOk)
195 {
196     if (!M_BITMAPDATA)
197         m_refData = new wxBitmapRefData;
198
199     M_BITMAPDATA->m_ok = isOk;
200 }
201
202 void wxBitmap::SetPalette(const wxPalette& palette)
203 {
204     if (!M_BITMAPDATA)
205         m_refData = new wxBitmapRefData;
206
207     M_BITMAPDATA->m_bitmapPalette = palette ;
208 }
209
210 void wxBitmap::SetMask(wxMask *mask)
211 {
212     if (!M_BITMAPDATA)
213         m_refData = new wxBitmapRefData;
214
215     M_BITMAPDATA->m_bitmapMask = mask ;
216 }
217
218 bool wxBitmap::Ok() const
219 {
220     return m_refData && M_BITMAPDATA->m_ok;
221 }
222
223 wxPalette* wxBitmap::GetPalette() const
224 {
225     if(!m_refData)
226         return NULL;
227     return &M_BITMAPDATA->m_bitmapPalette;
228 }
229
230 wxMask* wxBitmap::GetMask() const
231 {
232     if(!m_refData)
233         return NULL;
234     return M_BITMAPDATA->m_bitmapMask;
235 }
236
237 int wxBitmap::GetDepth() const
238 {
239     if(!m_refData)
240         return 0;
241     return M_BITMAPDATA->m_depth;
242 }
243
244 int wxBitmap::GetWidth() const
245 {
246     if(!m_refData)
247         return 0;
248     return M_BITMAPDATA->m_width;
249 }
250
251 int wxBitmap::GetHeight() const
252 {
253     if(!m_refData)
254         return 0;
255     return M_BITMAPDATA->m_height;
256 }
257
258 bool wxBitmap::Create(int w, int h, int d)
259 {
260     UnRef();
261
262     m_refData = new wxBitmapRefData;
263
264     M_BITMAPDATA->m_width = w;
265     M_BITMAPDATA->m_height = h;
266     M_BITMAPDATA->m_depth = d;
267
268     /* TODO: create new bitmap */
269
270     return M_BITMAPDATA->m_ok;
271 }
272
273 bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
274 {
275     wxAutoNSAutoreleasePool pool;
276     UnRef();
277
278     m_refData = new wxBitmapRefData;
279
280     NSBitmapImageRep *imageRep = [NSBitmapImageRep
281         imageRepWithContentsOfFile:wxNSStringWithWxString(filename)];
282
283     if(imageRep)
284     {
285         M_BITMAPDATA->m_width = [imageRep pixelsWide];
286         M_BITMAPDATA->m_height = [imageRep pixelsHigh];
287         M_BITMAPDATA->m_depth = 24; // FIXME
288         M_BITMAPDATA->m_ok = true;
289         M_BITMAPDATA->m_numColors = 0;
290         M_BITMAPDATA->m_quality = 0;
291         M_BITMAPDATA->m_cocoaNSBitmapImageRep = [imageRep retain];
292         M_BITMAPDATA->m_bitmapMask = NULL;
293         return true;
294     }
295     wxImage image;
296     if(!image.LoadFile(filename,type))
297         return false;
298     if(!image.Ok())
299         return false;
300     *this = wxBitmap(image);
301     return true;
302 }
303
304 bool wxBitmap::Create(void *data, wxBitmapType type, int width, int height, int depth)
305 {
306     UnRef();
307
308     m_refData = new wxBitmapRefData;
309
310     return false;
311 }
312
313 bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, const wxPalette *palette) const
314 {
315     return false;
316 }
317
318 bool wxBitmap::CopyFromIcon(const wxIcon& icno)
319 {
320     return false;
321 }
322
323 wxBitmap wxBitmap::GetSubBitmap(wxRect const&) const
324 {
325     return wxNullBitmap;
326 }
327
328 wxImage wxBitmap::ConvertToImage() const
329 {
330     if(!M_BITMAPDATA->m_ok)
331         return wxImage(5,5)/*wxNullImage*/;
332     return wxImage(M_BITMAPDATA->m_width,M_BITMAPDATA->m_height);
333 }
334
335 bool wxBitmap::CreateFromXpm(const char **xpm)
336 {
337 #if wxUSE_IMAGE && wxUSE_XPM
338     UnRef();
339
340     wxCHECK_MSG( xpm, false, wxT("invalid XPM data") )
341
342     wxXPMDecoder decoder;
343     wxImage img = decoder.ReadData(xpm);
344     wxCHECK_MSG( img.Ok(), false, wxT("invalid XPM data") )
345
346     *this = wxBitmap(img);
347     return true;
348 #else
349     return false;
350 #endif
351 }
352
353 bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
354 {
355     UnRef();
356
357     wxCHECK_MSG(image.Ok(), false, wxT("invalid image"));
358     wxCHECK_MSG(depth == -1 || depth == 1, false, wxT("invalid bitmap depth"));
359
360     m_refData = new wxBitmapRefData();
361
362     M_BITMAPDATA->m_width = image.GetWidth();
363     M_BITMAPDATA->m_height = image.GetHeight();
364     NSBitmapImageRep *bitmapImage = [[NSBitmapImageRep alloc]
365             initWithBitmapDataPlanes: NULL
366             pixelsWide: image.GetWidth()
367             pixelsHigh: image.GetHeight()
368             bitsPerSample: 8
369             samplesPerPixel: 3
370             hasAlpha: NO
371             isPlanar: NO
372             colorSpaceName: NSCalibratedRGBColorSpace
373             bytesPerRow: 0
374             bitsPerPixel: 0];
375
376     const int numBytes = image.GetWidth()*image.GetHeight()*3;
377     memcpy([bitmapImage bitmapData], image.GetData(), numBytes);
378     // TODO: Alpha and convert to desired depth
379     M_BITMAPDATA->m_depth = 24;
380     M_BITMAPDATA->m_ok = true;
381     M_BITMAPDATA->m_numColors = 0;
382     M_BITMAPDATA->m_quality = 0;
383     M_BITMAPDATA->m_cocoaNSBitmapImageRep = bitmapImage;
384     M_BITMAPDATA->m_bitmapMask = NULL;
385     return true;
386 }
387
388 // ========================================================================
389 // wxMask
390 // ========================================================================
391
392 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
393
394 wxMask::wxMask()
395 {
396 /* TODO
397     m_maskBitmap = 0;
398 */
399 }
400
401 // Construct a mask from a bitmap and a colour indicating
402 // the transparent area
403 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
404 {
405 /* TODO
406     m_maskBitmap = 0;
407 */
408     Create(bitmap, colour);
409 }
410
411 // Construct a mask from a bitmap and a palette index indicating
412 // the transparent area
413 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
414 {
415 /* TODO
416     m_maskBitmap = 0;
417 */
418
419     Create(bitmap, paletteIndex);
420 }
421
422 // Construct a mask from a mono bitmap (copies the bitmap).
423 wxMask::wxMask(const wxBitmap& bitmap)
424 {
425 /* TODO
426     m_maskBitmap = 0;
427 */
428
429     Create(bitmap);
430 }
431
432 wxMask::~wxMask()
433 {
434 // TODO: delete mask bitmap
435 }
436
437 // Create a mask from a mono bitmap (copies the bitmap).
438 bool wxMask::Create(const wxBitmap& bitmap)
439 {
440 // TODO
441     return FALSE;
442 }
443
444 // Create a mask from a bitmap and a palette index indicating
445 // the transparent area
446 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
447 {
448 // TODO
449     return FALSE;
450 }
451
452 // Create a mask from a bitmap and a colour indicating
453 // the transparent area
454 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
455 {
456 // TODO
457     return FALSE;
458 }
459