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