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