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