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