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