]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/bitmap.cpp
copyright update
[wxWidgets.git] / src / mgl / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: bitmap.cpp
3 // Author: Vaclav Slavik
4 // RCS-ID: $Id$
5 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 #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 static 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
54 //-----------------------------------------------------------------------------
55 // helpers
56 //-----------------------------------------------------------------------------
57
58 // Convert wxColour into it's quantized value in lower-precision
59 // pixel format (needed for masking by colour).
60 static 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
74 //-----------------------------------------------------------------------------
75 // wxMask
76 //-----------------------------------------------------------------------------
77
78 IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
79
80 wxMask::wxMask()
81 {
82 m_bitmap = NULL;
83 }
84
85 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
86 {
87 m_bitmap = NULL;
88 Create(bitmap, colour);
89 }
90
91 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
92 {
93 m_bitmap = NULL;
94 Create(bitmap, paletteIndex);
95 }
96
97 wxMask::wxMask(const wxBitmap& bitmap)
98 {
99 m_bitmap = NULL;
100 Create(bitmap);
101 }
102
103 wxMask::~wxMask()
104 {
105 delete m_bitmap;
106 }
107
108 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
109 {
110 delete m_bitmap;
111 m_bitmap = NULL;
112
113 wxColour clr(wxQuantizeColour(colour, bitmap));
114
115 wxImage imgSrc(bitmap.ConvertToImage());
116 imgSrc.SetMask(FALSE);
117 wxImage image(imgSrc.ConvertToMono(clr.Red(), clr.Green(), clr.Blue()));
118 if ( !image.Ok() ) return FALSE;
119
120 m_bitmap = new wxBitmap(image, 1);
121
122 return m_bitmap->Ok();
123 }
124
125 bool 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
137 bool 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
154 class wxBitmapRefData: public wxObjectRefData
155 {
156 public:
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
168 wxBitmapRefData::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
178 wxBitmapRefData::~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
191 IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler,wxObject)
192 IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxBitmapBase)
193
194 wxBitmap::wxBitmap(int width, int height, int depth)
195 {
196 Create(width, height, depth);
197 }
198
199
200 static 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
207 bool 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
271 bool 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
281 return TRUE;
282 }
283
284 wxBitmap::wxBitmap(const wxImage& image, int depth)
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
295 MGLMemoryDC idc(width, height, 24, &gs_pixel_format_wxImage,
296 width * 3, (void*)image.GetData(), NULL);
297 wxASSERT_MSG( idc.isValid(), wxT("cannot create custom MGLDC") );
298
299 MGLDevCtx *bdc = CreateTmpDC();
300
301 if ( GetDepth() <= 8 && image.HasPalette() )
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
318 wxImage wxBitmap::ConvertToImage() const
319 {
320 wxCHECK_MSG( Ok(), FALSE, wxT("invalid bitmap") );
321
322 int width, height;
323 width = GetWidth();
324 height = GetHeight();
325
326 wxImage image(width, height);
327 wxASSERT_MSG( image.Ok(), wxT("cannot create image") );
328
329 MGLMemoryDC idc(width, height, 24, &gs_pixel_format_wxImage,
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
361 wxBitmap::wxBitmap(const wxBitmap& bmp)
362 {
363 Ref(bmp);
364 }
365
366 wxBitmap::wxBitmap(const wxString &filename, wxBitmapType type)
367 {
368 LoadFile(filename, type);
369 }
370
371 wxBitmap::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;
383 }
384
385 wxBitmap& wxBitmap::operator = (const wxBitmap& bmp)
386 {
387 if ( *this == bmp ) return (*this);
388 Ref(bmp);
389 return *this;
390 }
391
392 bool wxBitmap::operator == (const wxBitmap& bmp) const
393 {
394 return (m_refData == bmp.m_refData);
395 }
396
397 bool wxBitmap::operator != (const wxBitmap& bmp) const
398 {
399 return (m_refData != bmp.m_refData);
400 }
401
402 bool wxBitmap::Ok() const
403 {
404 return (m_refData != NULL && M_BMPDATA->m_bitmap != NULL);
405 }
406
407 int wxBitmap::GetHeight() const
408 {
409 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
410
411 return M_BMPDATA->m_height;
412 }
413
414 int wxBitmap::GetWidth() const
415 {
416 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
417
418 return M_BMPDATA->m_width;
419 }
420
421 int wxBitmap::GetDepth() const
422 {
423 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
424
425 return M_BMPDATA->m_bpp;
426 }
427
428 wxMask *wxBitmap::GetMask() const
429 {
430 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
431
432 return M_BMPDATA->m_mask;
433 }
434
435 void 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
443 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
444 {
445 wxBitmap *bmp = (wxBitmap*)(&icon);
446 *this = *bmp;
447 return TRUE;
448 }
449
450 wxBitmap 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
478 void 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
500 MGLDevCtx *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:
522 cnt = 0;
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
534 bool 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
571 bool 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
595 wxPalette *wxBitmap::GetPalette() const
596 {
597 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
598
599 return M_BMPDATA->m_palette;
600 }
601
602 void 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
619 void wxBitmap::SetHeight(int height)
620 {
621 if (!m_refData) m_refData = new wxBitmapRefData();
622
623 M_BMPDATA->m_height = height;
624 }
625
626 void wxBitmap::SetWidth(int width)
627 {
628 if (!m_refData) m_refData = new wxBitmapRefData();
629
630 M_BMPDATA->m_width = width;
631 }
632
633 void wxBitmap::SetDepth(int depth)
634 {
635 if (!m_refData) m_refData = new wxBitmapRefData();
636
637 M_BMPDATA->m_bpp = depth;
638 }
639
640 bitmap_t *wxBitmap::GetMGLbitmap_t() const
641 {
642 return M_BMPDATA->m_bitmap;
643 }
644
645
646
647 //-----------------------------------------------------------------------------
648 // wxBitmap I/O handlers
649 //-----------------------------------------------------------------------------
650
651 class wxMGLBitmapHandler: public wxBitmapHandler
652 {
653 public:
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
667 wxMGLBitmapHandler::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
677 bool 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
754 bool 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
789 class wxPNGBitmapHandler: public wxMGLBitmapHandler
790 {
791 public:
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
800 bool 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
870 class 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
886 wxICOBitmapHandler::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
896 bool 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
937 bool 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 }