]> git.saurik.com Git - wxWidgets.git/blame - src/mgl/bitmap.cpp
don't strip &s from tooltips (patch 1488318)
[wxWidgets.git] / src / mgl / bitmap.cpp
CommitLineData
32b8ec41 1/////////////////////////////////////////////////////////////////////////////
127eab18 2// Name: src/mgl/bitmap.cpp
32b8ec41
VZ
3// Author: Vaclav Slavik
4// RCS-ID: $Id$
c41c20a5 5// Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
65571936 6// Licence: wxWindows licence
32b8ec41
VZ
7/////////////////////////////////////////////////////////////////////////////
8
32b8ec41
VZ
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"
88a7a4e1
WS
17
18#ifndef WX_PRECOMP
19 #include "wx/intl.h"
e4db172a 20 #include "wx/log.h"
de6185e2 21 #include "wx/utils.h"
f38924e8 22 #include "wx/dcmemory.h"
923d28da 23 #include "wx/icon.h"
88a7a4e1
WS
24#endif
25
32b8ec41
VZ
26#include "wx/filefn.h"
27#include "wx/image.h"
32b8ec41
VZ
28#include "wx/image.h"
29#include "wx/xpmdecod.h"
30
31#include "wx/mgl/private.h"
32
33#include <mgraph.hpp>
34
35//-----------------------------------------------------------------------------
36// MGL pixel formats:
37//-----------------------------------------------------------------------------
38
39static pixel_format_t gs_pixel_format_15 =
127eab18
WS
40 {0x1F,0x0A,3, 0x1F,0x05,3, 0x1F,0x00,3, 0x01,0x0F,7}; // 555 15bpp
41
32b8ec41 42static pixel_format_t gs_pixel_format_16 =
127eab18 43 {0x1F,0x0B,3, 0x3F,0x05,2, 0x1F,0x00,3, 0x00,0x00,0}; // 565 16bpp
32b8ec41
VZ
44
45static pixel_format_t gs_pixel_format_24 =
127eab18 46 {0xFF,0x10,0, 0xFF,0x08,0, 0xFF,0x00,0, 0x00,0x00,0}; // RGB 24bpp
32b8ec41
VZ
47
48static pixel_format_t gs_pixel_format_32 =
127eab18 49 {0xFF,0x18,0, 0xFF,0x10,0, 0xFF,0x08,0, 0xFF,0x00,0}; // RGBA 32bpp
32b8ec41 50
553dce51 51static pixel_format_t gs_pixel_format_wxImage =
127eab18 52 {0xFF,0x00,0, 0xFF,0x08,0, 0xFF,0x10,0, 0x00,0x00,0}; // RGB 24bpp for wxImage
553dce51 53
cdcb56fc
VS
54//-----------------------------------------------------------------------------
55// helpers
56//-----------------------------------------------------------------------------
57
58// Convert wxColour into it's quantized value in lower-precision
59// pixel format (needed for masking by colour).
60static wxColour wxQuantizeColour(const wxColour& clr, const wxBitmap& bmp)
61{
62 pixel_format_t *pf = bmp.GetMGLbitmap_t()->pf;
127eab18 63
cdcb56fc
VS
64 if ( pf->redAdjust == 0 && pf->greenAdjust == 0 && pf->blueAdjust == 0 )
65 return clr;
66 else
127eab18
WS
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));
cdcb56fc
VS
70}
71
72
73
32b8ec41
VZ
74//-----------------------------------------------------------------------------
75// wxMask
76//-----------------------------------------------------------------------------
77
78IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
79
80wxMask::wxMask()
81{
82 m_bitmap = NULL;
83}
84
85wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
86{
87 m_bitmap = NULL;
88 Create(bitmap, colour);
89}
90
91wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
92{
93 m_bitmap = NULL;
94 Create(bitmap, paletteIndex);
95}
96
97wxMask::wxMask(const wxBitmap& bitmap)
98{
99 m_bitmap = NULL;
100 Create(bitmap);
101}
102
103wxMask::~wxMask()
104{
105 delete m_bitmap;
106}
107
108bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
109{
110 delete m_bitmap;
111 m_bitmap = NULL;
127eab18 112
cdcb56fc 113 wxColour clr(wxQuantizeColour(colour, bitmap));
32b8ec41 114
cdcb56fc 115 wxImage imgSrc(bitmap.ConvertToImage());
127eab18 116 imgSrc.SetMask(false);
cdcb56fc 117 wxImage image(imgSrc.ConvertToMono(clr.Red(), clr.Green(), clr.Blue()));
127eab18
WS
118 if ( !image.Ok() )
119 return false;
cdcb56fc 120
32b8ec41
VZ
121 m_bitmap = new wxBitmap(image, 1);
122
123 return m_bitmap->Ok();
124}
125
126bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
127{
128 unsigned char r,g,b;
129 wxPalette *pal = bitmap.GetPalette();
130
127eab18
WS
131 wxCHECK_MSG( pal, false, wxT("Cannot create mask from bitmap without palette") );
132
32b8ec41
VZ
133 pal->GetRGB(paletteIndex, &r, &g, &b);
134
135 return Create(bitmap, wxColour(r, g, b));
136}
137
138bool wxMask::Create(const wxBitmap& bitmap)
139{
140 delete m_bitmap;
141 m_bitmap = NULL;
142
127eab18
WS
143 wxCHECK_MSG( bitmap.Ok(), false, wxT("Invalid bitmap") );
144 wxCHECK_MSG( bitmap.GetDepth() == 1, false, wxT("Cannot create mask from colour bitmap") );
32b8ec41
VZ
145
146 m_bitmap = new wxBitmap(bitmap);
127eab18 147 return true;
32b8ec41
VZ
148}
149
150
151//-----------------------------------------------------------------------------
152// wxBitmap
153//-----------------------------------------------------------------------------
154
155class wxBitmapRefData: public wxObjectRefData
156{
157public:
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
169wxBitmapRefData::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
179wxBitmapRefData::~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
192IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler,wxObject)
193IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxBitmapBase)
194
32b8ec41
VZ
195wxBitmap::wxBitmap(int width, int height, int depth)
196{
197 Create(width, height, depth);
32b8ec41
VZ
198}
199
200
127eab18 201static bitmap_t *MyMGL_createBitmap(int width, int height,
32b8ec41
VZ
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
208bool wxBitmap::Create(int width, int height, int depth)
209{
210 UnRef();
211
637b7e4f 212 wxCHECK_MSG( (width > 0) && (height > 0), false, wxT("invalid bitmap size") );
127eab18
WS
213
214 pixel_format_t pf_dummy;
215 pixel_format_t *pf;
32b8ec41
VZ
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);
127eab18 224 mglDepth = g_displayDC->getBitsPerPixel();
32b8ec41
VZ
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:
6a64f8d4 244 wxFAIL_MSG(wxT("invalid bitmap depth"));
127eab18 245 return false;
32b8ec41
VZ
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
127eab18 263 // set to black and all other colors set to white.
32b8ec41
VZ
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
272bool wxBitmap::CreateFromXpm(const char **bits)
273{
637b7e4f 274 wxCHECK_MSG( bits != NULL, false, wxT("invalid bitmap data") );
127eab18 275
32b8ec41
VZ
276 wxXPMDecoder decoder;
277 wxImage img = decoder.ReadData(bits);
637b7e4f 278 wxCHECK_MSG( img.Ok(), false, wxT("invalid bitmap data") );
127eab18 279
32b8ec41 280 *this = wxBitmap(img);
127eab18
WS
281
282 return true;
32b8ec41
VZ
283}
284
f043bf8d 285wxBitmap::wxBitmap(const wxImage& image, int depth)
32b8ec41
VZ
286{
287 long width, height;
288
637b7e4f 289 wxCHECK_RET( image.Ok(), wxT("invalid image") );
127eab18 290
32b8ec41
VZ
291 width = image.GetWidth();
292 height = image.GetHeight();
293
294 if ( !Create(width, height, depth) ) return;
127eab18 295
553dce51 296 MGLMemoryDC idc(width, height, 24, &gs_pixel_format_wxImage,
32b8ec41
VZ
297 width * 3, (void*)image.GetData(), NULL);
298 wxASSERT_MSG( idc.isValid(), wxT("cannot create custom MGLDC") );
299
300 MGLDevCtx *bdc = CreateTmpDC();
301
f9619ece 302 if ( GetDepth() <= 8 && image.HasPalette() )
32b8ec41
VZ
303 SetPalette(image.GetPalette());
304
305 bdc->bitBlt(idc, 0, 0, width, height, 0, 0, MGL_REPLACE_MODE);
306 delete bdc;
127eab18 307
32b8ec41
VZ
308 if ( image.HasMask() )
309 {
310 wxImage mask_image = image.ConvertToMono(image.GetMaskRed(),
311 image.GetMaskGreen(),
312 image.GetMaskBlue());
127eab18 313 mask_image.SetMask(false);
32b8ec41
VZ
314 wxBitmap mask_bmp(mask_image, 1);
315 SetMask(new wxMask(mask_bmp));
316 }
317}
318
319wxImage wxBitmap::ConvertToImage() const
320{
db28c33c 321 wxCHECK_MSG( Ok(), wxImage(), wxT("invalid bitmap") );
32b8ec41 322
a4bbc9f7 323 int width, height;
32b8ec41
VZ
324 width = GetWidth();
325 height = GetHeight();
127eab18 326
32b8ec41
VZ
327 wxImage image(width, height);
328 wxASSERT_MSG( image.Ok(), wxT("cannot create image") );
127eab18 329
553dce51 330 MGLMemoryDC idc(width, height, 24, &gs_pixel_format_wxImage,
32b8ec41
VZ
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));
127eab18 336
32b8ec41
VZ
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);
127eab18 345 image.SetMask(true);
32b8ec41
VZ
346
347 wxDC tmpDC;
127eab18 348 tmpDC.SetMGLDC(&idc, false);
32b8ec41
VZ
349 tmpDC.SetBackground(wxBrush(wxColour(16,16,16), wxSOLID));
350 tmpDC.Clear();
127eab18 351 tmpDC.DrawBitmap(*this, 0, 0, true);
32b8ec41
VZ
352 }
353 else
354 {
127eab18 355 image.SetMask(false);
32b8ec41
VZ
356 idc.putBitmap(0, 0, M_BMPDATA->m_bitmap, MGL_REPLACE_MODE);
357 }
358
359 return image;
360}
361
32b8ec41
VZ
362wxBitmap::wxBitmap(const wxString &filename, wxBitmapType type)
363{
364 LoadFile(filename, type);
32b8ec41
VZ
365}
366
367wxBitmap::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;
32b8ec41
VZ
379}
380
32b8ec41
VZ
381bool wxBitmap::operator == (const wxBitmap& bmp) const
382{
383 return (m_refData == bmp.m_refData);
384}
385
386bool wxBitmap::operator != (const wxBitmap& bmp) const
387{
388 return (m_refData != bmp.m_refData);
389}
390
391bool wxBitmap::Ok() const
392{
393 return (m_refData != NULL && M_BMPDATA->m_bitmap != NULL);
394}
395
396int wxBitmap::GetHeight() const
397{
398 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
399
400 return M_BMPDATA->m_height;
401}
402
403int wxBitmap::GetWidth() const
404{
405 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
406
407 return M_BMPDATA->m_width;
408}
409
410int wxBitmap::GetDepth() const
411{
412 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
413
414 return M_BMPDATA->m_bpp;
415}
416
417wxMask *wxBitmap::GetMask() const
418{
419 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
420
421 return M_BMPDATA->m_mask;
422}
423
424void 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
432bool wxBitmap::CopyFromIcon(const wxIcon& icon)
433{
434 wxBitmap *bmp = (wxBitmap*)(&icon);
435 *this = *bmp;
127eab18 436 return true;
32b8ec41
VZ
437}
438
439wxBitmap 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();
127eab18 453 tdc->putBitmapSection(rect.x, rect.y,
32b8ec41
VZ
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
467void 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
489MGLDevCtx *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,
127eab18 497 M_BMPDATA->m_bitmap->surface,
32b8ec41
VZ
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;
127eab18 504
32b8ec41
VZ
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:
a4bbc9f7 511 cnt = 0;
32b8ec41
VZ
512 wxFAIL_MSG( wxT("bitmap with this depth cannot have palette") );
513 break;
514 }
127eab18 515
32b8ec41
VZ
516 tdc->setPalette(M_BMPDATA->m_bitmap->pal, cnt, 0);
517 tdc->realizePalette(cnt, 0, FALSE);
518 }
127eab18 519
32b8ec41
VZ
520 return tdc;
521}
522
523bool wxBitmap::LoadFile(const wxString &name, wxBitmapType type)
524{
525 UnRef();
127eab18
WS
526
527 if ( type == wxBITMAP_TYPE_BMP || type == wxBITMAP_TYPE_PNG ||
32b8ec41
VZ
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());
127eab18 534 return false;
32b8ec41
VZ
535 }
536 }
127eab18 537
32b8ec41
VZ
538 wxBitmapHandler *handler = FindHandler(type);
539
127eab18 540 if ( handler == NULL )
32b8ec41
VZ
541 {
542 wxImage image;
543 if ( !image.LoadFile(name, type) || !image.Ok() )
544 {
127eab18
WS
545 wxLogError("no bitmap handler for type %d defined.", type);
546 return false;
32b8ec41
VZ
547 }
548 else
549 {
550 *this = wxBitmap(image);
127eab18 551 return true;
32b8ec41
VZ
552 }
553 }
554
555 m_refData = new wxBitmapRefData();
556
557 return handler->LoadFile(this, name, type, -1, -1);
558}
559
560bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, const wxPalette *palette) const
561{
127eab18 562 wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
32b8ec41
VZ
563
564 wxBitmapHandler *handler = FindHandler(type);
565
127eab18 566 if ( handler == NULL )
32b8ec41
VZ
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);
127eab18 577 return false;
32b8ec41
VZ
578 }
579 }
580
581 return handler->SaveFile(this, filename, type, palette);
582}
583
584wxPalette *wxBitmap::GetPalette() const
585{
586 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
587
588 return M_BMPDATA->m_palette;
589}
590
591void 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;
127eab18 600
32b8ec41
VZ
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
608void wxBitmap::SetHeight(int height)
609{
610 if (!m_refData) m_refData = new wxBitmapRefData();
611
612 M_BMPDATA->m_height = height;
613}
614
615void wxBitmap::SetWidth(int width)
616{
617 if (!m_refData) m_refData = new wxBitmapRefData();
618
619 M_BMPDATA->m_width = width;
620}
621
622void wxBitmap::SetDepth(int depth)
623{
624 if (!m_refData) m_refData = new wxBitmapRefData();
625
626 M_BMPDATA->m_bpp = depth;
627}
628
629bitmap_t *wxBitmap::GetMGLbitmap_t() const
630{
631 return M_BMPDATA->m_bitmap;
632}
633
634
635
636//-----------------------------------------------------------------------------
637// wxBitmap I/O handlers
638//-----------------------------------------------------------------------------
639
640class wxMGLBitmapHandler: public wxBitmapHandler
641{
642public:
643 wxMGLBitmapHandler(wxBitmapType type,
644 const wxString& extension, const wxString& name);
645
127eab18
WS
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; }
32b8ec41
VZ
653
654 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
655 int desiredWidth, int desiredHeight);
127eab18 656 virtual bool SaveFile(const wxBitmap *bitmap, const wxString& name,
32b8ec41
VZ
657 int type, const wxPalette *palette = NULL);
658};
659
127eab18 660wxMGLBitmapHandler::wxMGLBitmapHandler(wxBitmapType type,
32b8ec41
VZ
661 const wxString& extension,
662 const wxString& name)
663 : wxBitmapHandler()
664{
665 SetType(type);
666 SetName(name);
667 SetExtension(extension);
668}
669
127eab18
WS
670bool wxMGLBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name,
671 long flags,
672 int WXUNUSED(desiredWidth),
32b8ec41
VZ
673 int WXUNUSED(desiredHeight))
674{
675 int width, height, bpp;
676 pixel_format_t pf;
677 wxString fullname;
678 wxMemoryDC dc;
127eab18 679
32b8ec41
VZ
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;
127eab18 691 }
32b8ec41
VZ
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) )
127eab18 698 return false;
32b8ec41 699 bitmap->Create(width, height, -1);
127eab18 700 if ( !bitmap->Ok() ) return false;
32b8ec41
VZ
701 dc.SelectObject(*bitmap);
702 if ( !dc.GetMGLDC()->loadBitmapIntoDC(fullname.mb_str(), 0, 0, TRUE) )
127eab18 703 return false;
32b8ec41
VZ
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) )
127eab18 709 return false;
32b8ec41 710 bitmap->Create(width, height, -1);
127eab18 711 if ( !bitmap->Ok() ) return false;
32b8ec41
VZ
712 dc.SelectObject(*bitmap);
713 if ( !dc.GetMGLDC()->loadJPEGIntoDC(fullname.mb_str(), 0, 0, TRUE) )
127eab18 714 return false;
32b8ec41
VZ
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) )
127eab18 720 return false;
32b8ec41 721 bitmap->Create(width, height, -1);
127eab18 722 if ( !bitmap->Ok() ) return false;
32b8ec41
VZ
723 dc.SelectObject(*bitmap);
724 if ( !dc.GetMGLDC()->loadPNGIntoDC(fullname.mb_str(), 0, 0, TRUE) )
127eab18 725 return false;
32b8ec41
VZ
726 break;
727
728 case wxBITMAP_TYPE_PCX:
729 case wxBITMAP_TYPE_PCX_RESOURCE:
730 if ( !MGL_getPCXSize(fullname.mb_str(), &width, &height, &bpp) )
127eab18 731 return false;
32b8ec41 732 bitmap->Create(width, height, -1);
127eab18 733 if ( !bitmap->Ok() ) return false;
32b8ec41
VZ
734 dc.SelectObject(*bitmap);
735 if ( !dc.GetMGLDC()->loadPCXIntoDC(fullname.mb_str(), 0, 0, TRUE) )
127eab18 736 return false;
32b8ec41
VZ
737 break;
738
739 default:
740 wxFAIL_MSG(wxT("Unsupported image format."));
741 break;
742 }
743
127eab18 744 return true;
32b8ec41
VZ
745}
746
127eab18 747bool wxMGLBitmapHandler::SaveFile(const wxBitmap *bitmap, const wxString& name,
32b8ec41
VZ
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:
127eab18 761 return (bool)tdc->saveBitmapFromDC(name.mb_str(), 0, 0, w, h);
32b8ec41 762 case wxBITMAP_TYPE_JPEG:
127eab18 763 return (bool)tdc->saveJPEGFromDC(name.mb_str(), 0, 0, w, h, 75);
32b8ec41 764 case wxBITMAP_TYPE_PNG:
127eab18 765 return (bool)tdc->savePNGFromDC(name.mb_str(), 0, 0, w, h);
32b8ec41 766 case wxBITMAP_TYPE_PCX:
127eab18 767 return (bool)tdc->savePCXFromDC(name.mb_str(), 0, 0, w, h);
32b8ec41 768 }
127eab18
WS
769
770 return false;
32b8ec41
VZ
771}
772
773
774
127eab18 775// let's handle PNGs in special way because they have alpha channel
32b8ec41
VZ
776// which we can access via bitmap_t most easily
777class wxPNGBitmapHandler: public wxMGLBitmapHandler
778{
779public:
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
127eab18
WS
788bool wxPNGBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name,
789 long flags,
32b8ec41
VZ
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) )
127eab18 802 return false;
32b8ec41
VZ
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
127eab18 809 return wxMGLBitmapHandler::LoadFile(bitmap, name, flags,
32b8ec41
VZ
810 desiredWidth, desiredHeight);
811 }
127eab18 812
32b8ec41 813 bitmap_t *bmp = MGL_loadPNG(fullname.mb_str(), TRUE);
127eab18
WS
814
815 if ( bmp == NULL ) return false;
32b8ec41
VZ
816
817 bitmap->Create(bmp->width, bmp->height, -1);
127eab18
WS
818 if ( !bitmap->Ok() ) return false;
819
32b8ec41
VZ
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);
127eab18 825
32b8ec41
VZ
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 {
127eab18 836 if ( ((((*s) >> bmp->pf->alphaPos) & bmp->pf->alphaMask)
c0f02dbc 837 << bmp->pf->alphaAdjust) < 128 )
32b8ec41
VZ
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 }
127eab18 849
32b8ec41 850 MGL_unloadBitmap(bmp);
127eab18
WS
851
852 return true;
32b8ec41
VZ
853}
854
855
856
857
858class wxICOBitmapHandler: public wxBitmapHandler
859{
860 public:
861 wxICOBitmapHandler(wxBitmapType type,
862 const wxString& extension, const wxString& name);
127eab18
WS
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
32b8ec41
VZ
872 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
873 int desiredWidth, int desiredHeight);
127eab18 874 virtual bool SaveFile(const wxBitmap *bitmap, const wxString& name,
32b8ec41
VZ
875 int type, const wxPalette *palette = NULL);
876};
877
127eab18 878wxICOBitmapHandler::wxICOBitmapHandler(wxBitmapType type,
32b8ec41
VZ
879 const wxString& extension,
880 const wxString& name)
881 : wxBitmapHandler()
882{
883 SetType(type);
884 SetName(name);
885 SetExtension(extension);
886}
887
127eab18
WS
888bool wxICOBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name,
889 long flags,
890 int WXUNUSED(desiredWidth),
32b8ec41
VZ
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);
127eab18 898 else
32b8ec41
VZ
899 icon = MGL_loadIcon(name.mb_str(), TRUE);
900
127eab18 901 if ( icon == NULL ) return false;
32b8ec41
VZ
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);
127eab18 921
32b8ec41
VZ
922 bitmap->SetMask(new wxMask(mask));
923
924 MGL_unloadIcon(icon);
127eab18
WS
925
926 return true;
32b8ec41
VZ
927}
928
127eab18
WS
929bool wxICOBitmapHandler::SaveFile(const wxBitmap *WXUNUSED(bitmap),
930 const wxString& WXUNUSED(name),
931 int WXUNUSED(type),
932 const wxPalette * WXUNUSED(palette))
32b8ec41 933{
127eab18 934 return false;
32b8ec41
VZ
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}