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