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