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