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