]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/bitmap.cpp
Changed CanPaste to just check IsSupported.
[wxWidgets.git] / src / mgl / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: bitmap.cpp
3 // Author: Vaclav Slavik
4 // RCS-ID: $Id$
5 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 #ifdef __GNUG__
10 #pragma implementation "bitmap.h"
11 #endif
12
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #include "wx/bitmap.h"
21 #include "wx/icon.h"
22 #include "wx/filefn.h"
23 #include "wx/image.h"
24 #include "wx/dcmemory.h"
25 #include "wx/utils.h"
26 #include "wx/log.h"
27 #include "wx/intl.h"
28 #include "wx/image.h"
29 #include "wx/xpmdecod.h"
30
31 #include "wx/mgl/private.h"
32
33 #include <mgraph.hpp>
34
35 //-----------------------------------------------------------------------------
36 // MGL pixel formats:
37 //-----------------------------------------------------------------------------
38
39 static pixel_format_t gs_pixel_format_15 =
40 {0x1F,0x0A,3, 0x1F,0x05,3, 0x1F,0x00,3, 0x01,0x0F,7}; // 555 15bpp
41
42 static pixel_format_t gs_pixel_format_16 =
43 {0x1F,0x0B,3, 0x3F,0x05,2, 0x1F,0x00,3, 0x00,0x00,0}; // 565 16bpp
44
45 static pixel_format_t gs_pixel_format_24 =
46 {0xFF,0x10,0, 0xFF,0x08,0, 0xFF,0x00,0, 0x00,0x00,0}; // RGB 24bpp
47
48 static pixel_format_t gs_pixel_format_32 =
49 {0xFF,0x18,0, 0xFF,0x10,0, 0xFF,0x08,0, 0xFF,0x00,0}; // RGBA 32bpp
50
51 static pixel_format_t gs_pixel_format_wxImage =
52 {0xFF,0x00,0, 0xFF,0x08,0, 0xFF,0x10,0, 0x00,0x00,0}; // RGB 24bpp for wxImage
53
54 //-----------------------------------------------------------------------------
55 // helpers
56 //-----------------------------------------------------------------------------
57
58 // Convert wxColour into it's quantized value in lower-precision
59 // pixel format (needed for masking by colour).
60 static wxColour wxQuantizeColour(const wxColour& clr, const wxBitmap& bmp)
61 {
62 pixel_format_t *pf = bmp.GetMGLbitmap_t()->pf;
63
64 if ( pf->redAdjust == 0 && pf->greenAdjust == 0 && pf->blueAdjust == 0 )
65 return clr;
66 else
67 return wxColour((clr.Red() >> pf->redAdjust) << pf->redAdjust,
68 (clr.Green() >> pf->greenAdjust) << pf->greenAdjust,
69 (clr.Blue() >> pf->blueAdjust) << pf->blueAdjust);
70 }
71
72
73
74 //-----------------------------------------------------------------------------
75 // wxMask
76 //-----------------------------------------------------------------------------
77
78 IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
79
80 wxMask::wxMask()
81 {
82 m_bitmap = NULL;
83 }
84
85 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
86 {
87 m_bitmap = NULL;
88 Create(bitmap, colour);
89 }
90
91 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
92 {
93 m_bitmap = NULL;
94 Create(bitmap, paletteIndex);
95 }
96
97 wxMask::wxMask(const wxBitmap& bitmap)
98 {
99 m_bitmap = NULL;
100 Create(bitmap);
101 }
102
103 wxMask::~wxMask()
104 {
105 delete m_bitmap;
106 }
107
108 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
109 {
110 delete m_bitmap;
111 m_bitmap = NULL;
112
113 wxColour clr(wxQuantizeColour(colour, bitmap));
114
115 wxImage imgSrc(bitmap.ConvertToImage());
116 imgSrc.SetMask(FALSE);
117 wxImage image(imgSrc.ConvertToMono(clr.Red(), clr.Green(), clr.Blue()));
118 if ( !image.Ok() ) return FALSE;
119
120 m_bitmap = new wxBitmap(image, 1);
121
122 return m_bitmap->Ok();
123 }
124
125 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
126 {
127 unsigned char r,g,b;
128 wxPalette *pal = bitmap.GetPalette();
129
130 wxCHECK_MSG( pal, FALSE, wxT("Cannot create mask from bitmap without palette") );
131
132 pal->GetRGB(paletteIndex, &r, &g, &b);
133
134 return Create(bitmap, wxColour(r, g, b));
135 }
136
137 bool wxMask::Create(const wxBitmap& bitmap)
138 {
139 delete m_bitmap;
140 m_bitmap = NULL;
141
142 wxCHECK_MSG( bitmap.Ok(), FALSE, wxT("Invalid bitmap") );
143 wxCHECK_MSG( bitmap.GetDepth() == 1, FALSE, wxT("Cannot create mask from colour bitmap") );
144
145 m_bitmap = new wxBitmap(bitmap);
146 return TRUE;
147 }
148
149
150 //-----------------------------------------------------------------------------
151 // wxBitmap
152 //-----------------------------------------------------------------------------
153
154 class wxBitmapRefData: public wxObjectRefData
155 {
156 public:
157 wxBitmapRefData();
158 ~wxBitmapRefData();
159
160 int m_width;
161 int m_height;
162 int m_bpp;
163 wxPalette *m_palette;
164 wxMask *m_mask;
165 bitmap_t *m_bitmap;
166 };
167
168 wxBitmapRefData::wxBitmapRefData()
169 {
170 m_mask = NULL;
171 m_width = 0;
172 m_height = 0;
173 m_bpp = 0;
174 m_palette = NULL;
175 m_bitmap = NULL;
176 }
177
178 wxBitmapRefData::~wxBitmapRefData()
179 {
180 if ( m_bitmap )
181 MGL_unloadBitmap(m_bitmap);
182 delete m_mask;
183 delete m_palette;
184 }
185
186 //-----------------------------------------------------------------------------
187
188 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
189
190
191 IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler,wxObject)
192 IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxBitmapBase)
193
194 wxBitmap::wxBitmap()
195 {
196 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
197 }
198
199 wxBitmap::wxBitmap(int width, int height, int depth)
200 {
201 Create(width, height, depth);
202
203 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
204 }
205
206
207 static bitmap_t *MyMGL_createBitmap(int width, int height,
208 int bpp, pixel_format_t *pf)
209 {
210 MGLMemoryDC mdc(width, height, bpp, pf);
211 return MGL_getBitmapFromDC(mdc.getDC(), 0, 0, width, height, TRUE);
212 }
213
214 bool wxBitmap::Create(int width, int height, int depth)
215 {
216 UnRef();
217
218 wxCHECK_MSG( (width > 0) && (height > 0), FALSE, wxT("invalid bitmap size") )
219
220 pixel_format_t pf_dummy, *pf;
221 int mglDepth = depth;
222
223 switch ( depth )
224 {
225 case -1:
226 wxASSERT_MSG( g_displayDC, wxT("MGL display DC not created yet.") );
227
228 g_displayDC->getPixelFormat(pf_dummy);
229 mglDepth = g_displayDC->getBitsPerPixel();
230 pf = &pf_dummy;
231 break;
232 case 1:
233 case 8:
234 pf = NULL;
235 break;
236 case 15:
237 pf = &gs_pixel_format_15;
238 break;
239 case 16:
240 pf = &gs_pixel_format_16;
241 break;
242 case 24:
243 pf = &gs_pixel_format_24;
244 break;
245 case 32:
246 pf = &gs_pixel_format_32;
247 break;
248 default:
249 wxASSERT_MSG( 0, wxT("invalid bitmap depth") );
250 return FALSE;
251 break;
252 }
253
254 m_refData = new wxBitmapRefData();
255 M_BMPDATA->m_mask = (wxMask *) NULL;
256 M_BMPDATA->m_palette = (wxPalette *) NULL;
257 M_BMPDATA->m_width = width;
258 M_BMPDATA->m_height = height;
259 M_BMPDATA->m_bpp = mglDepth;
260
261 if ( mglDepth != 1 )
262 {
263 M_BMPDATA->m_bitmap = MyMGL_createBitmap(width, height, mglDepth, pf);
264 }
265 else
266 {
267 // MGL does not support mono DCs, so we have to emulate them with
268 // 8bpp ones. We do that by using a special palette with color 0
269 // set to black and all other colors set to white.
270
271 M_BMPDATA->m_bitmap = MyMGL_createBitmap(width, height, 8, pf);
272 SetMonoPalette(wxColour(255, 255, 255), wxColour(0, 0, 0));
273 }
274
275 return Ok();
276 }
277
278 bool wxBitmap::CreateFromXpm(const char **bits)
279 {
280 wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") )
281
282 wxXPMDecoder decoder;
283 wxImage img = decoder.ReadData(bits);
284 wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid bitmap data") )
285
286 *this = wxBitmap(img);
287
288 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
289
290 return TRUE;
291 }
292
293 wxBitmap::wxBitmap(const wxImage& image, int depth = -1)
294 {
295 long width, height;
296
297 wxCHECK_RET( image.Ok(), wxT("invalid image") )
298
299 width = image.GetWidth();
300 height = image.GetHeight();
301
302 if ( !Create(width, height, depth) ) return;
303
304 MGLMemoryDC idc(width, height, 24, &gs_pixel_format_wxImage,
305 width * 3, (void*)image.GetData(), NULL);
306 wxASSERT_MSG( idc.isValid(), wxT("cannot create custom MGLDC") );
307
308 MGLDevCtx *bdc = CreateTmpDC();
309
310 if ( depth <= 8 && image.HasPalette() )
311 SetPalette(image.GetPalette());
312
313 bdc->bitBlt(idc, 0, 0, width, height, 0, 0, MGL_REPLACE_MODE);
314 delete bdc;
315
316 if ( image.HasMask() )
317 {
318 wxImage mask_image = image.ConvertToMono(image.GetMaskRed(),
319 image.GetMaskGreen(),
320 image.GetMaskBlue());
321 mask_image.SetMask(FALSE);
322 wxBitmap mask_bmp(mask_image, 1);
323 SetMask(new wxMask(mask_bmp));
324 }
325 }
326
327 wxImage wxBitmap::ConvertToImage() const
328 {
329 wxCHECK_MSG( Ok(), FALSE, wxT("invalid bitmap") );
330
331 int width, height;
332 width = GetWidth();
333 height = GetHeight();
334
335 wxImage image(width, height);
336 wxASSERT_MSG( image.Ok(), wxT("cannot create image") );
337
338 MGLMemoryDC idc(width, height, 24, &gs_pixel_format_wxImage,
339 width * 3, (void*)image.GetData(), NULL);
340 wxASSERT_MSG( idc.isValid(), wxT("cannot create custom MGLDC") );
341
342 if ( M_BMPDATA->m_palette )
343 image.SetPalette(*(M_BMPDATA->m_palette));
344
345 if ( GetMask() )
346 {
347 // in consistency with other ports, we convert parts covered
348 // by the mask to <16,16,16> colour and set that colour to image's
349 // mask. We do that by OR-blitting the mask over image with
350 // bg colour set to black and fg colour to <16,16,16>
351
352 image.SetMaskColour(16, 16, 16);
353 image.SetMask(TRUE);
354
355 wxDC tmpDC;
356 tmpDC.SetMGLDC(&idc, FALSE);
357 tmpDC.SetBackground(wxBrush(wxColour(16,16,16), wxSOLID));
358 tmpDC.Clear();
359 tmpDC.DrawBitmap(*this, 0, 0, TRUE);
360 }
361 else
362 {
363 image.SetMask(FALSE);
364 idc.putBitmap(0, 0, M_BMPDATA->m_bitmap, MGL_REPLACE_MODE);
365 }
366
367 return image;
368 }
369
370 wxBitmap::wxBitmap(const wxBitmap& bmp)
371 {
372 Ref(bmp);
373
374 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
375 }
376
377 wxBitmap::wxBitmap(const wxString &filename, wxBitmapType type)
378 {
379 LoadFile(filename, type);
380
381 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
382 }
383
384 wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
385 {
386 wxCHECK_RET( depth == 1, wxT("can only create mono bitmap from XBM data") );
387
388 if ( !Create(width, height, 1) ) return;
389 MGLDevCtx *bdc = CreateTmpDC();
390 wxCurrentDCSwitcher curDC(bdc);
391 bdc->setColor(1);
392 bdc->setBackColor(0);
393 bdc->clearDevice();
394 bdc->putMonoImage(0, 0, width, (width + 7) / 8, height, (void*)bits);
395 delete bdc;
396
397 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
398 }
399
400 wxBitmap::~wxBitmap()
401 {
402 if ( wxTheBitmapList ) wxTheBitmapList->DeleteObject(this);
403 }
404
405 wxBitmap& wxBitmap::operator = (const wxBitmap& bmp)
406 {
407 if ( *this == bmp ) return (*this);
408 Ref(bmp);
409 return *this;
410 }
411
412 bool wxBitmap::operator == (const wxBitmap& bmp) const
413 {
414 return (m_refData == bmp.m_refData);
415 }
416
417 bool wxBitmap::operator != (const wxBitmap& bmp) const
418 {
419 return (m_refData != bmp.m_refData);
420 }
421
422 bool wxBitmap::Ok() const
423 {
424 return (m_refData != NULL && M_BMPDATA->m_bitmap != NULL);
425 }
426
427 int wxBitmap::GetHeight() const
428 {
429 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
430
431 return M_BMPDATA->m_height;
432 }
433
434 int wxBitmap::GetWidth() const
435 {
436 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
437
438 return M_BMPDATA->m_width;
439 }
440
441 int wxBitmap::GetDepth() const
442 {
443 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
444
445 return M_BMPDATA->m_bpp;
446 }
447
448 wxMask *wxBitmap::GetMask() const
449 {
450 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
451
452 return M_BMPDATA->m_mask;
453 }
454
455 void wxBitmap::SetMask(wxMask *mask)
456 {
457 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
458
459 delete M_BMPDATA->m_mask;
460 M_BMPDATA->m_mask = mask;
461 }
462
463 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
464 {
465 wxBitmap *bmp = (wxBitmap*)(&icon);
466 *this = *bmp;
467 return TRUE;
468 }
469
470 wxBitmap wxBitmap::GetSubBitmap(const wxRect& rect) const
471 {
472 wxCHECK_MSG( Ok() &&
473 (rect.x >= 0) && (rect.y >= 0) &&
474 (rect.x+rect.width <= M_BMPDATA->m_width) && (rect.y+rect.height <= M_BMPDATA->m_height),
475 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
476
477 wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
478 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
479
480 if ( GetPalette() )
481 ret.SetPalette(*GetPalette());
482
483 MGLDevCtx *tdc = ret.CreateTmpDC();
484 tdc->putBitmapSection(rect.x, rect.y,
485 rect.x + rect.width, rect.y + rect.height,
486 0, 0, M_BMPDATA->m_bitmap, MGL_REPLACE_MODE);
487 delete tdc;
488
489 if ( GetMask() )
490 {
491 wxBitmap submask = GetMask()->GetBitmap()->GetSubBitmap(rect);
492 ret.SetMask(new wxMask(submask));
493 }
494
495 return ret;
496 }
497
498 void wxBitmap::SetMonoPalette(const wxColour& fg, const wxColour& bg)
499 {
500 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
501
502 palette_t *mono = M_BMPDATA->m_bitmap->pal;
503
504 wxCHECK_RET( M_BMPDATA->m_bpp == 1, wxT("bitmap is not 1bpp") );
505 wxCHECK_RET( mono != NULL, wxT("bitmap w/o palette") );
506
507 mono[0].red = bg.Red();
508 mono[0].green = bg.Green();
509 mono[0].blue = bg.Blue();
510 mono[0].alpha = 0;
511 for (size_t i = 1; i < 256; i++)
512 {
513 mono[i].red = fg.Red();
514 mono[i].green = fg.Green();
515 mono[i].blue = fg.Blue();
516 mono[i].alpha = 0;
517 }
518 }
519
520 MGLDevCtx *wxBitmap::CreateTmpDC() const
521 {
522 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
523
524 MGLDevCtx *tdc = new MGLMemoryDC(GetWidth(), GetHeight(),
525 M_BMPDATA->m_bitmap->bitsPerPixel,
526 M_BMPDATA->m_bitmap->pf,
527 M_BMPDATA->m_bitmap->bytesPerLine,
528 M_BMPDATA->m_bitmap->surface,
529 NULL);
530 wxCHECK_MSG( tdc->isValid(), NULL, wxT("cannot create temporary MGLDC") );
531
532 if ( M_BMPDATA->m_bitmap->pal != NULL )
533 {
534 int cnt;
535
536 switch (M_BMPDATA->m_bitmap->bitsPerPixel)
537 {
538 case 2: cnt = 2; break;
539 case 4: cnt = 16; break;
540 case 8: cnt = 256; break;
541 default:
542 cnt = 0;
543 wxFAIL_MSG( wxT("bitmap with this depth cannot have palette") );
544 break;
545 }
546
547 tdc->setPalette(M_BMPDATA->m_bitmap->pal, cnt, 0);
548 tdc->realizePalette(cnt, 0, FALSE);
549 }
550
551 return tdc;
552 }
553
554 bool wxBitmap::LoadFile(const wxString &name, wxBitmapType type)
555 {
556 UnRef();
557
558 if ( type == wxBITMAP_TYPE_BMP || type == wxBITMAP_TYPE_PNG ||
559 type == wxBITMAP_TYPE_PCX || type == wxBITMAP_TYPE_JPEG )
560 {
561 // prevent accidental loading of bitmap from $MGL_ROOT:
562 if ( !wxFileExists(name) )
563 {
564 wxLogError(_("File %s does not exist."), name.c_str());
565 return FALSE;
566 }
567 }
568
569 wxBitmapHandler *handler = FindHandler(type);
570
571 if ( handler == NULL )
572 {
573 wxImage image;
574 if ( !image.LoadFile(name, type) || !image.Ok() )
575 {
576 wxLogError("no bitmap handler for type %d defined.", type);
577 return FALSE;
578 }
579 else
580 {
581 *this = wxBitmap(image);
582 return TRUE;
583 }
584 }
585
586 m_refData = new wxBitmapRefData();
587
588 return handler->LoadFile(this, name, type, -1, -1);
589 }
590
591 bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, const wxPalette *palette) const
592 {
593 wxCHECK_MSG( Ok(), FALSE, wxT("invalid bitmap") );
594
595 wxBitmapHandler *handler = FindHandler(type);
596
597 if ( handler == NULL )
598 {
599 wxImage image = ConvertToImage();
600 if ( palette )
601 image.SetPalette(*palette);
602
603 if ( image.Ok() )
604 return image.SaveFile(filename, type);
605 else
606 {
607 wxLogError("no bitmap handler for type %d defined.", type);
608 return FALSE;
609 }
610 }
611
612 return handler->SaveFile(this, filename, type, palette);
613 }
614
615 wxPalette *wxBitmap::GetPalette() const
616 {
617 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
618
619 return M_BMPDATA->m_palette;
620 }
621
622 void wxBitmap::SetPalette(const wxPalette& palette)
623 {
624 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
625 wxCHECK_RET( GetDepth() > 1 && GetDepth() <= 8, wxT("cannot set palette for bitmap of this depth") );
626
627 delete M_BMPDATA->m_palette;
628 M_BMPDATA->m_palette = NULL;
629
630 if ( !palette.Ok() ) return;
631
632 M_BMPDATA->m_palette = new wxPalette(palette);
633
634 int cnt = palette.GetColoursCount();
635 palette_t *pal = palette.GetMGLpalette_t();
636 memcpy(M_BMPDATA->m_bitmap->pal, pal, cnt * sizeof(palette_t));
637 }
638
639 void wxBitmap::SetHeight(int height)
640 {
641 if (!m_refData) m_refData = new wxBitmapRefData();
642
643 M_BMPDATA->m_height = height;
644 }
645
646 void wxBitmap::SetWidth(int width)
647 {
648 if (!m_refData) m_refData = new wxBitmapRefData();
649
650 M_BMPDATA->m_width = width;
651 }
652
653 void wxBitmap::SetDepth(int depth)
654 {
655 if (!m_refData) m_refData = new wxBitmapRefData();
656
657 M_BMPDATA->m_bpp = depth;
658 }
659
660 bitmap_t *wxBitmap::GetMGLbitmap_t() const
661 {
662 return M_BMPDATA->m_bitmap;
663 }
664
665
666
667 //-----------------------------------------------------------------------------
668 // wxBitmap I/O handlers
669 //-----------------------------------------------------------------------------
670
671 class wxMGLBitmapHandler: public wxBitmapHandler
672 {
673 public:
674 wxMGLBitmapHandler(wxBitmapType type,
675 const wxString& extension, const wxString& name);
676
677 virtual bool Create(wxBitmap *bitmap, void *data, long flags,
678 int width, int height, int depth = 1)
679 { return FALSE; }
680
681 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
682 int desiredWidth, int desiredHeight);
683 virtual bool SaveFile(const wxBitmap *bitmap, const wxString& name,
684 int type, const wxPalette *palette = NULL);
685 };
686
687 wxMGLBitmapHandler::wxMGLBitmapHandler(wxBitmapType type,
688 const wxString& extension,
689 const wxString& name)
690 : wxBitmapHandler()
691 {
692 SetType(type);
693 SetName(name);
694 SetExtension(extension);
695 }
696
697 bool wxMGLBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name,
698 long flags,
699 int WXUNUSED(desiredWidth),
700 int WXUNUSED(desiredHeight))
701 {
702 int width, height, bpp;
703 pixel_format_t pf;
704 wxString fullname;
705 wxMemoryDC dc;
706
707 switch (flags)
708 {
709 case wxBITMAP_TYPE_BMP_RESOURCE:
710 case wxBITMAP_TYPE_JPEG_RESOURCE:
711 case wxBITMAP_TYPE_PNG_RESOURCE:
712 case wxBITMAP_TYPE_PCX_RESOURCE:
713 fullname = name + wxT(".bmp");
714 break;
715 default:
716 fullname= name;
717 break;
718 }
719
720 switch (flags)
721 {
722 case wxBITMAP_TYPE_BMP:
723 case wxBITMAP_TYPE_BMP_RESOURCE:
724 if ( !MGL_getBitmapSize(fullname.mb_str(), &width, &height, &bpp, &pf) )
725 return FALSE;
726 bitmap->Create(width, height, -1);
727 if ( !bitmap->Ok() ) return FALSE;
728 dc.SelectObject(*bitmap);
729 if ( !dc.GetMGLDC()->loadBitmapIntoDC(fullname.mb_str(), 0, 0, TRUE) )
730 return FALSE;
731 break;
732
733 case wxBITMAP_TYPE_JPEG:
734 case wxBITMAP_TYPE_JPEG_RESOURCE:
735 if ( !MGL_getJPEGSize(fullname.mb_str(), &width, &height, &bpp, &pf) )
736 return FALSE;
737 bitmap->Create(width, height, -1);
738 if ( !bitmap->Ok() ) return FALSE;
739 dc.SelectObject(*bitmap);
740 if ( !dc.GetMGLDC()->loadJPEGIntoDC(fullname.mb_str(), 0, 0, TRUE) )
741 return FALSE;
742 break;
743
744 case wxBITMAP_TYPE_PNG:
745 case wxBITMAP_TYPE_PNG_RESOURCE:
746 if ( !MGL_getPNGSize(fullname.mb_str(), &width, &height, &bpp, &pf) )
747 return FALSE;
748 bitmap->Create(width, height, -1);
749 if ( !bitmap->Ok() ) return FALSE;
750 dc.SelectObject(*bitmap);
751 if ( !dc.GetMGLDC()->loadPNGIntoDC(fullname.mb_str(), 0, 0, TRUE) )
752 return FALSE;
753 break;
754
755 case wxBITMAP_TYPE_PCX:
756 case wxBITMAP_TYPE_PCX_RESOURCE:
757 if ( !MGL_getPCXSize(fullname.mb_str(), &width, &height, &bpp) )
758 return FALSE;
759 bitmap->Create(width, height, -1);
760 if ( !bitmap->Ok() ) return FALSE;
761 dc.SelectObject(*bitmap);
762 if ( !dc.GetMGLDC()->loadPCXIntoDC(fullname.mb_str(), 0, 0, TRUE) )
763 return FALSE;
764 break;
765
766 default:
767 wxFAIL_MSG(wxT("Unsupported image format."));
768 break;
769 }
770
771 return TRUE;
772 }
773
774 bool wxMGLBitmapHandler::SaveFile(const wxBitmap *bitmap, const wxString& name,
775 int type, const wxPalette * WXUNUSED(palette))
776 {
777 wxMemoryDC mem;
778 MGLDevCtx *tdc;
779 int w = bitmap->GetWidth(),
780 h = bitmap->GetHeight();
781
782 mem.SelectObject(*bitmap);
783 tdc = mem.GetMGLDC();
784
785 switch (type)
786 {
787 case wxBITMAP_TYPE_BMP:
788 return tdc->saveBitmapFromDC(name.mb_str(), 0, 0, w, h);
789 break;
790 case wxBITMAP_TYPE_JPEG:
791 return tdc->saveJPEGFromDC(name.mb_str(), 0, 0, w, h, 75);
792 break;
793 case wxBITMAP_TYPE_PNG:
794 return tdc->savePNGFromDC(name.mb_str(), 0, 0, w, h);
795 break;
796 case wxBITMAP_TYPE_PCX:
797 return tdc->savePCXFromDC(name.mb_str(), 0, 0, w, h);
798 break;
799 default:
800 return FALSE;
801 break;
802 }
803 }
804
805
806
807 // let's handle PNGs in special way because they have alpha channel
808 // which we can access via bitmap_t most easily
809 class wxPNGBitmapHandler: public wxMGLBitmapHandler
810 {
811 public:
812 wxPNGBitmapHandler(wxBitmapType type,
813 const wxString& extension, const wxString& name)
814 : wxMGLBitmapHandler(type, extension, name) {}
815
816 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
817 int desiredWidth, int desiredHeight);
818 };
819
820 bool wxPNGBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name,
821 long flags,
822 int desiredWidth, int desiredHeight)
823 {
824 int width, height, bpp;
825 pixel_format_t pf;
826 wxString fullname;
827
828 if ( flags == wxBITMAP_TYPE_PNG_RESOURCE )
829 fullname = name + wxT(".png");
830 else
831 fullname = name;
832
833 if ( !MGL_getPNGSize(fullname.mb_str(), &width, &height, &bpp, &pf) )
834 return FALSE;
835
836 if ( bpp != 32 )
837 {
838 // We can load ordinary PNGs faster with 'normal' MGL handler.
839 // Only RGBA PNGs need to be processed in special way because
840 // we have to convert alpha channel to mask
841 return wxMGLBitmapHandler::LoadFile(bitmap, name, flags,
842 desiredWidth, desiredHeight);
843 }
844
845 bitmap_t *bmp = MGL_loadPNG(fullname.mb_str(), TRUE);
846
847 if ( bmp == NULL ) return FALSE;
848
849 bitmap->Create(bmp->width, bmp->height, -1);
850 if ( !bitmap->Ok() ) return FALSE;
851
852 // convert bmp to display's depth and write it to *bitmap:
853 wxMemoryDC dc;
854 dc.SelectObject(*bitmap);
855 dc.GetMGLDC()->putBitmap(0, 0, bmp, MGL_REPLACE_MODE);
856 dc.SelectObject(wxNullBitmap);
857
858 // create mask, if bmp contains alpha channel (ARGB format):
859 if ( bmp->bitsPerPixel == 32 )
860 {
861 int x, y;
862 wxUint32 *s = (wxUint32*)bmp->surface;
863 for (y = 0; y < bmp->height; y++)
864 {
865 s = ((wxUint32*)bmp->surface) + y * bmp->bytesPerLine/4;
866 for (x = 0; x < bmp->width; x++, s ++)
867 {
868 if ( ((((*s) >> bmp->pf->rsvdPos) & bmp->pf->rsvdMask)
869 << bmp->pf->rsvdAdjust) < 128 )
870 *s = 0;
871 else
872 *s = 0x00FFFFFF; // white
873 }
874 }
875 wxBitmap mask(bmp->width, bmp->height, 1);
876 dc.SelectObject(mask);
877 dc.GetMGLDC()->putBitmap(0, 0, bmp, MGL_REPLACE_MODE);
878 dc.SelectObject(wxNullBitmap);
879 bitmap->SetMask(new wxMask(mask));
880 }
881
882 MGL_unloadBitmap(bmp);
883
884 return TRUE;
885 }
886
887
888
889
890 class wxICOBitmapHandler: public wxBitmapHandler
891 {
892 public:
893 wxICOBitmapHandler(wxBitmapType type,
894 const wxString& extension, const wxString& name);
895
896 virtual bool Create(wxBitmap *bitmap, void *data, long flags,
897 int width, int height, int depth = 1)
898 { return FALSE; }
899
900 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
901 int desiredWidth, int desiredHeight);
902 virtual bool SaveFile(const wxBitmap *bitmap, const wxString& name,
903 int type, const wxPalette *palette = NULL);
904 };
905
906 wxICOBitmapHandler::wxICOBitmapHandler(wxBitmapType type,
907 const wxString& extension,
908 const wxString& name)
909 : wxBitmapHandler()
910 {
911 SetType(type);
912 SetName(name);
913 SetExtension(extension);
914 }
915
916 bool wxICOBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name,
917 long flags,
918 int WXUNUSED(desiredWidth),
919 int WXUNUSED(desiredHeight))
920 {
921 icon_t *icon = NULL;
922 MGLDevCtx *dc;
923
924 if ( flags == wxBITMAP_TYPE_ICO_RESOURCE )
925 icon = MGL_loadIcon(wxString(name + wxT(".ico")).mb_str(), TRUE);
926 else
927 icon = MGL_loadIcon(name.mb_str(), TRUE);
928
929 if ( icon == NULL ) return FALSE;
930
931 bitmap->Create(icon->xorMask.width, icon->xorMask.height);
932
933 wxMemoryDC mem;
934 mem.SelectObject(*bitmap);
935 dc = mem.GetMGLDC();
936 dc->putBitmap(0, 0, &(icon->xorMask), MGL_REPLACE_MODE);
937 mem.SelectObject(wxNullBitmap);
938
939 wxBitmap mask(icon->xorMask.width, icon->xorMask.height, 1);
940 mem.SelectObject(mask);
941 dc = mem.GetMGLDC();
942
943 wxCurrentDCSwitcher curDC(dc);
944 dc->setColor(0);
945 dc->setBackColor(1);
946 dc->clearDevice();
947 dc->putMonoImage(0, 0, icon->xorMask.width, icon->byteWidth,
948 icon->xorMask.height, (void*)icon->andMask);
949
950 bitmap->SetMask(new wxMask(mask));
951
952 MGL_unloadIcon(icon);
953
954 return TRUE;
955 }
956
957 bool wxICOBitmapHandler::SaveFile(const wxBitmap *bitmap, const wxString& name,
958 int type, const wxPalette * WXUNUSED(palette))
959 {
960 return FALSE;
961 }
962
963
964
965
966 /*static*/ void wxBitmap::InitStandardHandlers()
967 {
968 AddHandler(new wxMGLBitmapHandler(wxBITMAP_TYPE_BMP, wxT("bmp"), wxT("Windows bitmap")));
969 AddHandler(new wxMGLBitmapHandler(wxBITMAP_TYPE_BMP_RESOURCE, wxEmptyString, wxT("Windows bitmap resource")));
970 AddHandler(new wxMGLBitmapHandler(wxBITMAP_TYPE_JPEG, wxT("jpg"), wxT("JPEG image")));
971 AddHandler(new wxMGLBitmapHandler(wxBITMAP_TYPE_JPEG_RESOURCE, wxEmptyString, wxT("JPEG resource")));
972 AddHandler(new wxMGLBitmapHandler(wxBITMAP_TYPE_PCX, wxT("pcx"), wxT("PCX image")));
973 AddHandler(new wxMGLBitmapHandler(wxBITMAP_TYPE_PCX_RESOURCE, wxEmptyString, wxT("PCX resource")));
974
975 AddHandler(new wxPNGBitmapHandler(wxBITMAP_TYPE_PNG, wxT("png"), wxT("PNG image")));
976 AddHandler(new wxPNGBitmapHandler(wxBITMAP_TYPE_PNG_RESOURCE, wxEmptyString, wxT("PNG resource")));
977
978 AddHandler(new wxICOBitmapHandler(wxBITMAP_TYPE_ICO, wxT("ico"), wxT("Icon resource")));
979 AddHandler(new wxICOBitmapHandler(wxBITMAP_TYPE_ICO_RESOURCE, wxEmptyString, wxT("Icon resource")));
980 }