]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/bitmap.cpp
minor clean up
[wxWidgets.git] / src / mgl / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: bitmap.cpp
3 // Author: Vaclav Slavik
4 // RCS-ID: $Id$
5 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
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
39 static pixel_format_t gs_pixel_format_15 =
40 {0x1F,0x0A,3, 0x1F,0x05,3, 0x1F,0x00,3, 0x01,0x0F,7}; // 555 15bpp
41
42 static pixel_format_t gs_pixel_format_16 =
43 {0x1F,0x0B,3, 0x3F,0x05,2, 0x1F,0x00,3, 0x00,0x00,0}; // 565 16bpp
44
45 static pixel_format_t gs_pixel_format_24 =
46 {0xFF,0x10,0, 0xFF,0x08,0, 0xFF,0x00,0, 0x00,0x00,0}; // RGB 24bpp
47
48 static pixel_format_t gs_pixel_format_32 =
49 {0xFF,0x18,0, 0xFF,0x10,0, 0xFF,0x08,0, 0xFF,0x00,0}; // RGBA 32bpp
50
51 //-----------------------------------------------------------------------------
52 // wxMask
53 //-----------------------------------------------------------------------------
54
55 IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
56
57 wxMask::wxMask()
58 {
59 m_bitmap = NULL;
60 }
61
62 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
63 {
64 m_bitmap = NULL;
65 Create(bitmap, colour);
66 }
67
68 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
69 {
70 m_bitmap = NULL;
71 Create(bitmap, paletteIndex);
72 }
73
74 wxMask::wxMask(const wxBitmap& bitmap)
75 {
76 m_bitmap = NULL;
77 Create(bitmap);
78 }
79
80 wxMask::~wxMask()
81 {
82 delete m_bitmap;
83 }
84
85 bool 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
99 bool 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
111 bool 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
128 class wxBitmapRefData: public wxObjectRefData
129 {
130 public:
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
142 wxBitmapRefData::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
152 wxBitmapRefData::~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
165 IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler,wxObject)
166 IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxBitmapBase)
167
168 wxBitmap::wxBitmap()
169 {
170 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
171 }
172
173 wxBitmap::wxBitmap(int width, int height, int depth)
174 {
175 Create(width, height, depth);
176
177 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
178 }
179
180
181 static 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
188 bool 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
252 bool 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
267 wxBitmap::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
301 wxImage wxBitmap::ConvertToImage() const
302 {
303 wxCHECK_MSG( Ok(), FALSE, wxT("invalid bitmap") );
304
305 int width, height;
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
344 wxBitmap::wxBitmap(const wxBitmap& bmp)
345 {
346 Ref(bmp);
347
348 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
349 }
350
351 wxBitmap::wxBitmap(const wxString &filename, wxBitmapType type)
352 {
353 LoadFile(filename, type);
354
355 if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this);
356 }
357
358 wxBitmap::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
374 wxBitmap::~wxBitmap()
375 {
376 if ( wxTheBitmapList ) wxTheBitmapList->DeleteObject(this);
377 }
378
379 wxBitmap& wxBitmap::operator = (const wxBitmap& bmp)
380 {
381 if ( *this == bmp ) return (*this);
382 Ref(bmp);
383 return *this;
384 }
385
386 bool wxBitmap::operator == (const wxBitmap& bmp) const
387 {
388 return (m_refData == bmp.m_refData);
389 }
390
391 bool wxBitmap::operator != (const wxBitmap& bmp) const
392 {
393 return (m_refData != bmp.m_refData);
394 }
395
396 bool wxBitmap::Ok() const
397 {
398 return (m_refData != NULL && M_BMPDATA->m_bitmap != NULL);
399 }
400
401 int wxBitmap::GetHeight() const
402 {
403 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
404
405 return M_BMPDATA->m_height;
406 }
407
408 int wxBitmap::GetWidth() const
409 {
410 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
411
412 return M_BMPDATA->m_width;
413 }
414
415 int wxBitmap::GetDepth() const
416 {
417 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
418
419 return M_BMPDATA->m_bpp;
420 }
421
422 wxMask *wxBitmap::GetMask() const
423 {
424 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
425
426 return M_BMPDATA->m_mask;
427 }
428
429 void 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
437 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
438 {
439 wxBitmap *bmp = (wxBitmap*)(&icon);
440 *this = *bmp;
441 return TRUE;
442 }
443
444 wxBitmap 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
472 void 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
494 MGLDevCtx *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:
516 cnt = 0;
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
528 bool 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
565 bool 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
589 wxPalette *wxBitmap::GetPalette() const
590 {
591 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
592
593 return M_BMPDATA->m_palette;
594 }
595
596 void 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
613 void wxBitmap::SetHeight(int height)
614 {
615 if (!m_refData) m_refData = new wxBitmapRefData();
616
617 M_BMPDATA->m_height = height;
618 }
619
620 void wxBitmap::SetWidth(int width)
621 {
622 if (!m_refData) m_refData = new wxBitmapRefData();
623
624 M_BMPDATA->m_width = width;
625 }
626
627 void wxBitmap::SetDepth(int depth)
628 {
629 if (!m_refData) m_refData = new wxBitmapRefData();
630
631 M_BMPDATA->m_bpp = depth;
632 }
633
634 bitmap_t *wxBitmap::GetMGLbitmap_t() const
635 {
636 return M_BMPDATA->m_bitmap;
637 }
638
639
640
641 //-----------------------------------------------------------------------------
642 // wxBitmap I/O handlers
643 //-----------------------------------------------------------------------------
644
645 class wxMGLBitmapHandler: public wxBitmapHandler
646 {
647 public:
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
661 wxMGLBitmapHandler::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
671 bool 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
748 bool 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
783 class wxPNGBitmapHandler: public wxMGLBitmapHandler
784 {
785 public:
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
794 bool 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
864 class 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
880 wxICOBitmapHandler::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
890 bool 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
931 bool 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 }