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