]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/bitmap.cpp
Visualage C++ V4.0 updates
[wxWidgets.git] / src / os2 / bitmap.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: bitmap.cpp
3// Purpose: wxBitmap
4// Author: David Webster
5// Modified by:
6// Created: 08/08/99
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifndef WX_PRECOMP
16 #include <stdio.h>
17
18 #include "wx/list.h"
19 #include "wx/utils.h"
20 #include "wx/app.h"
21 #include "wx/palette.h"
22 #include "wx/dcmemory.h"
23 #include "wx/bitmap.h"
24 #include "wx/icon.h"
25#endif
26
27#include "wx/os2/private.h"
28#include "wx/log.h"
29
30//#include "wx/msw/dib.h"
31#include "wx/image.h"
32
33// ----------------------------------------------------------------------------
34// macros
35// ----------------------------------------------------------------------------
36
37#if !USE_SHARED_LIBRARIES
38IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
39IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
40
41IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
42#endif
43
44// ============================================================================
45// implementation
46// ============================================================================
47
48// ----------------------------------------------------------------------------
49// wxBitmapRefData
50// ----------------------------------------------------------------------------
51
52wxBitmapRefData::wxBitmapRefData()
53{
54 m_nQuality = 0;
55 m_pSelectedInto = NULL;
56 m_nNumColors = 0;
57 m_pBitmapMask = NULL;
58}
59
60void wxBitmapRefData::Free()
61{
62 wxASSERT_MSG( !m_pSelectedInto,
63 wxT("deleting bitmap still selected into wxMemoryDC") );
64
65 if (m_hBitmap)
66 {
67 if ( !::GpiDeleteBitmap((HBITMAP)m_hBitmap) )
68 {
69 wxLogLastError("GpiDeleteBitmap(hbitmap)");
70 }
71 }
72
73 delete m_pBitmapMask;
74 m_pBitmapMask = NULL;
75}
76
77// ----------------------------------------------------------------------------
78// wxBitmap creation
79// ----------------------------------------------------------------------------
80
81// this function should be called from all wxBitmap ctors
82void wxBitmap::Init()
83{
84 // m_refData = NULL; done in the base class ctor
85
86 if (wxTheBitmapList)
87 wxTheBitmapList->AddBitmap(this);
88}
89
90bool wxBitmap::CopyFromIconOrCursor(
91 const wxGDIImage& rIcon
92)
93{
94 wxBitmapRefData* pRefData = new wxBitmapRefData;
95
96 m_refData = pRefData;
97
98 pRefData->m_nWidth = rIcon.GetWidth();
99 pRefData->m_nHeight = rIcon.GetHeight();
100 pRefData->m_nDepth = wxDisplayDepth();
101
102 pRefData->m_hBitmap = (WXHBITMAP)rIcon.GetHandle();
103 // no mask???
104 pRefData->m_pBitmapMask = new wxMask();
105
106#if WXWIN_COMPATIBILITY_2
107 pRefData->m_bOk = TRUE;
108#endif // WXWIN_COMPATIBILITY_2
109 return(TRUE);
110}
111
112bool wxBitmap::CopyFromCursor(
113 const wxCursor& rCursor
114)
115{
116 UnRef();
117
118 if (!rCursor.Ok())
119 return(FALSE);
120 return(CopyFromIconOrCursor(rCursor));
121}
122
123bool wxBitmap::CopyFromIcon(
124 const wxIcon& rIcon
125)
126{
127 UnRef();
128
129 if (!rIcon.Ok())
130 return(FALSE);
131
132#if WXWIN_COMPATIBILITY_2
133 refData->m_ok = TRUE;
134#endif // WXWIN_COMPATIBILITY_2
135
136 return CopyFromIconOrCursor(rIcon);
137}
138
139wxBitmap::~wxBitmap()
140{
141 if (wxTheBitmapList)
142 wxTheBitmapList->DeleteObject(this);
143}
144
145wxBitmap::wxBitmap(
146 const char zBits[]
147, int nTheWidth
148, int nTheHeight
149, int nNoBits
150)
151{
152 Init();
153
154 wxBitmapRefData* pRefData = new wxBitmapRefData;
155 BITMAPINFOHEADER2 vHeader;
156 BITMAPINFO2 vInfo;
157 HDC hDc;
158 HPS hPs;
159 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
160 SIZEL vSize = {0, 0};
161
162 wxASSERT(vHabmain != NULL);
163
164 hDc = ::DevOpenDC(vHabmain, OD_MEMORY, (PSZ)"*", 1L, (PDEVOPENDATA)&vDop, 0L);
165
166 vHeader.cbFix = sizeof(vHeader);
167 vHeader.cx = (USHORT)nTheWidth;
168 vHeader.cy = (USHORT)nTheHeight;
169 vHeader.cPlanes = 1L;
170 vHeader.cBitCount = nNoBits;
171 vHeader.ulCompression = BCA_UNCOMP;
172 vHeader.cxResolution = 0;
173 vHeader.cyResolution = 0;
174 vHeader.cclrUsed = 0;
175 vHeader.cclrImportant = 0;
176 vHeader.usUnits = BRU_METRIC;
177 vHeader.usRecording = BRA_BOTTOMUP;
178 vHeader.usRendering = BRH_NOTHALFTONED;
179 vHeader.cSize1 = 0;
180 vHeader.cSize2 = 0;
181 vHeader.ulColorEncoding = 0;
182 vHeader.ulIdentifier = 0;
183
184 hPs = ::GpiCreatePS(vHabmain, hDc, &vSize, GPIA_ASSOC | PU_PELS);
185 if (hPs == 0)
186 {
187 wxLogLastError("GpiCreatePS Failure");
188 }
189
190 m_hDc = hDc;
191 m_hPs = hPs;
192
193 m_refData = pRefData;
194
195 pRefData->m_nWidth = nTheWidth;
196 pRefData->m_nHeight = nTheHeight;
197 pRefData->m_nDepth = nNoBits;
198 pRefData->m_nNumColors = 0;
199 pRefData->m_pSelectedInto = NULL;
200
201 HBITMAP hBmp = ::GpiCreateBitmap(hPs, &vHeader, 0L, NULL, &vInfo);
202 if (!hBmp)
203 {
204 wxLogLastError("CreateBitmap");
205 }
206 SetHBITMAP((WXHBITMAP)hBmp);
207}
208
209// Create from XPM data
210wxBitmap::wxBitmap(
211 char** ppData
212, wxControl* WXUNUSED(pAnItem))
213{
214 Init();
215
216 (void)Create( (void *)ppData
217 ,wxBITMAP_TYPE_XPM_DATA
218 ,0
219 ,0
220 ,0
221 );
222}
223
224wxBitmap::wxBitmap(
225 int nW
226, int nH
227, int nD
228)
229{
230 Init();
231
232 (void)Create( nW
233 ,nH
234 ,nD
235 );
236}
237
238wxBitmap::wxBitmap(
239 void* pData
240, long lType
241, int nWidth
242, int nHeight
243, int nDepth
244)
245{
246 Init();
247
248 (void)Create( pData
249 ,lType
250 ,nWidth
251 ,nHeight
252 ,nDepth
253 );
254}
255
256wxBitmap::wxBitmap(
257 const wxString& rFilename
258, long lType
259)
260{
261 Init();
262
263 LoadFile( rFilename
264 ,(int)lType
265 );
266}
267
268bool wxBitmap::Create(
269 int nW
270, int nH
271, int nD
272)
273{
274 HBITMAP hBmp;
275 BITMAPINFOHEADER2 vHeader;
276 BITMAPINFO2 vInfo;
277 HPS hpsScreen;
278 HDC hdcScreen;
279 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
280 SIZEL vSize = {0, 0};
281 LONG lBitCount;
282
283 wxASSERT(vHabmain != NULL);
284
285 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
286 hdcScreen = ::GpiQueryDevice(hpsScreen);
287 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitCount);
288
289 vHeader.cbFix = sizeof(vHeader);
290 vHeader.cx = (USHORT)nW;
291 vHeader.cy = (USHORT)nH;
292 vHeader.cPlanes = (USHORT)nD;
293 vHeader.cBitCount = lBitCount;
294 vHeader.ulCompression = BCA_UNCOMP;
295 vHeader.cxResolution = 0;
296 vHeader.cyResolution = 0;
297 vHeader.cclrUsed = 0;
298 vHeader.cclrImportant = 0;
299 vHeader.usUnits = BRU_METRIC;
300 vHeader.usRecording = BRA_BOTTOMUP;
301 vHeader.usRendering = BRH_NOTHALFTONED;
302 vHeader.cSize1 = 0;
303 vHeader.cSize2 = 0;
304 vHeader.ulColorEncoding = 0;
305 vHeader.ulIdentifier = 0;
306
307 UnRef();
308 m_refData = new wxBitmapRefData;
309
310 GetBitmapData()->m_nWidth = nW;
311 GetBitmapData()->m_nHeight = nH;
312 GetBitmapData()->m_nDepth = nD;
313
314 if (nD > 0)
315 {
316 hBmp = ::GpiCreateBitmap(hpsScreen, &vHeader, 0L, NULL, &vInfo);
317 if (!hBmp)
318 {
319 wxLogLastError("CreateBitmap");
320 }
321 }
322 else
323 {
324 LONG lPlanes;
325
326 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes);
327 hBmp = ::GpiCreateBitmap(hpsScreen, &vHeader, 0L, NULL, &vInfo);
328 if (!hBmp)
329 {
330 wxLogLastError("CreateBitmap");
331 }
332 GetBitmapData()->m_nDepth = wxDisplayDepth();
333 }
334 SetHBITMAP((WXHBITMAP)hBmp);
335
336#if WXWIN_COMPATIBILITY_2
337 GetBitmapData()->m_bOk = hBmp != 0;
338#endif // WXWIN_COMPATIBILITY_2
339
340 return Ok();
341}
342
343bool wxBitmap::LoadFile(
344 const wxString& rFilename
345, long lType
346)
347{
348 UnRef();
349
350 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
351 ,wxBitmapHandler
352 );
353
354 if (pHandler)
355 {
356 m_refData = new wxBitmapRefData;
357
358 return(pHandler->LoadFile( this
359 ,rFilename
360 ,lType
361 , -1
362 , -1
363 ));
364 }
365 else
366 {
367 wxImage vImage;
368
369 if (!vImage.LoadFile(rFilename, lType) || !vImage.Ok() )
370 return(FALSE);
371
372 *this = vImage.ConvertToBitmap();
373
374 return(TRUE);
375 }
376}
377
378bool wxBitmap::Create(
379 void* pData
380, long lType
381, int nWidth
382, int nHeight
383, int nDepth
384)
385{
386 UnRef();
387
388 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
389 ,wxBitmapHandler
390 );
391
392 if (!pHandler)
393 {
394 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
395 "type %d defined."), lType);
396
397 return(FALSE);
398 }
399
400 m_refData = new wxBitmapRefData;
401
402 return(pHandler->Create( this
403 ,pData
404 ,lType
405 ,nWidth
406 ,nHeight
407 ,nDepth
408 ));
409}
410
411bool wxBitmap::SaveFile(
412 const wxString& rFilename
413, int lType
414, const wxPalette* pPalette
415)
416{
417 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
418 ,wxBitmapHandler
419 );
420
421 if (pHandler)
422 {
423 return pHandler->SaveFile( this
424 ,rFilename
425 ,lType
426 ,pPalette
427 );
428 }
429 else
430 {
431 // FIXME what about palette? shouldn't we use it?
432 wxImage vImage(*this);
433
434 if (!vImage.Ok())
435 return(FALSE);
436
437 return(vImage.SaveFile( rFilename
438 ,lType
439 ));
440 }
441}
442
443// ----------------------------------------------------------------------------
444// wxBitmap accessors
445// ----------------------------------------------------------------------------
446
447void wxBitmap::SetQuality(
448 int nQ
449)
450{
451 EnsureHasData();
452
453 GetBitmapData()->m_nQuality = nQ;
454}
455
456#if WXWIN_COMPATIBILITY_2
457void wxBitmap::SetOk(
458 bool bOk
459)
460{
461 EnsureHasData();
462
463 GetBitmapData()->m_bOk = bOk;
464}
465#endif // WXWIN_COMPATIBILITY_2
466
467void wxBitmap::SetPalette(
468 const wxPalette& rPalette
469)
470{
471 EnsureHasData();
472
473 GetBitmapData()->m_vBitmapPalette = rPalette;
474}
475
476void wxBitmap::SetMask(
477 wxMask* pMask
478)
479{
480 EnsureHasData();
481
482 GetBitmapData()->m_pBitmapMask = pMask;
483}
484
485// Will try something for OS/2 but not really sure how close
486// to the msw intent this is.
487wxBitmap wxBitmap::GetBitmapForDC(
488 wxDC& rDc
489) const
490{
491 wxMemoryDC vMemDC;
492 wxBitmap vTmpBitmap( this->GetWidth()
493 ,this->GetHeight()
494 ,rDc.GetDepth()
495 );
496 WXHBITMAP vOldBitmap;
497 HPS hMemoryPS;
498 HPS hPs;
499 POINTL vPoint[4];
500 SIZEL vSize = {0,0};
501
502 hMemoryPS = ::GpiCreatePS(vHabmain, (HDC)vMemDC.GetHDC(), &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
503 hPs = ::GpiCreatePS(vHabmain, (HDC)rDc.GetHDC(), &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
504
505 // TODO: Set the points
506
507 vOldBitmap = (WXHBITMAP)::GpiSetBitmap(hPs, (HBITMAP)vTmpBitmap.GetHBITMAP());
508 ::GpiBitBlt(hPs, hMemoryPS, 4L, vPoint, ROP_SRCCOPY, BBO_IGNORE);
509
510 return(vTmpBitmap);
511}
512
513// ----------------------------------------------------------------------------
514// wxMask
515// ----------------------------------------------------------------------------
516
517wxMask::wxMask()
518{
519 m_hMaskBitmap = 0;
520}
521
522// Construct a mask from a bitmap and a colour indicating
523// the transparent area
524wxMask::wxMask(
525 const wxBitmap& rBitmap
526, const wxColour& rColour
527)
528{
529 m_hMaskBitmap = 0;
530 Create( rBitmap
531 ,rColour
532 );
533}
534
535// Construct a mask from a bitmap and a palette index indicating
536// the transparent area
537wxMask::wxMask(
538 const wxBitmap& rBitmap
539, int nPaletteIndex
540)
541{
542 m_hMaskBitmap = 0;
543 Create( rBitmap
544 ,nPaletteIndex
545 );
546}
547
548// Construct a mask from a mono bitmap (copies the bitmap).
549wxMask::wxMask(
550 const wxBitmap& rBitmap
551)
552{
553 m_hMaskBitmap = 0;
554 Create(rBitmap);
555}
556
557wxMask::~wxMask()
558{
559 if (m_hMaskBitmap)
560 ::GpiDeleteBitmap((HBITMAP)m_hMaskBitmap);
561}
562
563// Create a mask from a mono bitmap (copies the bitmap).
564bool wxMask::Create(
565 const wxBitmap& rBitmap
566)
567{
568 BITMAPINFOHEADER2 vHeader;
569 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
570 SIZEL vSize = {0, 0};
571 POINTL vPoint[4];
572
573 if (m_hMaskBitmap)
574 {
575 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
576 m_hMaskBitmap = 0;
577 }
578 if (!rBitmap.Ok() || rBitmap.GetDepth() != 1)
579 {
580 return(FALSE);
581 }
582 vHeader.cbFix = sizeof(vHeader);
583 vHeader.cx = (USHORT)rBitmap.GetWidth();
584 vHeader.cy = (USHORT)rBitmap.GetHeight();
585 vHeader.cPlanes = 1;
586 vHeader.cBitCount = 1;
587
588 m_hMaskBitmap = (WXHBITMAP) ::GpiCreateBitmap( m_hPs
589 ,&vHeader
590 ,0L
591 ,NULL
592 ,NULL
593 );
594
595 HPS srcPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
596 ::GpiSetBitmap(srcPS, (HBITMAP)rBitmap.GetHBITMAP());
597 HPS destPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
598 ::GpiSetBitmap(srcPS, (HBITMAP)m_hMaskBitmap);
599 // TODO: Set the point array
600 ::GpiBitBlt(destPS, srcPS, 4L, vPoint, ROP_SRCCOPY , BBO_IGNORE);
601
602 ::GpiDestroyPS(srcPS);
603 ::GpiDestroyPS(destPS);
604 return(TRUE);
605}
606
607// Create a mask from a bitmap and a palette index indicating
608// the transparent area
609bool wxMask::Create(
610 const wxBitmap& rBitmap
611, int nPaletteIndex
612)
613{
614 if (m_hMaskBitmap)
615 {
616 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
617 m_hMaskBitmap = 0;
618 }
619 if (rBitmap.Ok() && rBitmap.GetPalette()->Ok())
620 {
621 unsigned char cRed;
622 unsigned char cGreen;
623 unsigned char cBlue;
624
625 if (rBitmap.GetPalette()->GetRGB( nPaletteIndex
626 ,&cRed
627 ,&cGreen
628 ,&cBlue
629 ))
630 {
631 wxColour vTransparentColour( cRed
632 ,cGreen
633 ,cBlue
634 );
635
636 return (Create( rBitmap
637 ,vTransparentColour
638 ));
639 }
640 }
641 return(FALSE);
642}
643
644// Create a mask from a bitmap and a colour indicating
645// the transparent area
646bool wxMask::Create(
647 const wxBitmap& rBitmap
648, const wxColour& rColour
649)
650{
651 BITMAPINFOHEADER2 vHeader;
652 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
653 SIZEL vSize = {0, 0};
654 POINTL vPoint[4];
655
656 if (m_hMaskBitmap)
657 {
658 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
659 m_hMaskBitmap = 0;
660 }
661 if (!rBitmap.Ok())
662 {
663 return(FALSE);
664 }
665
666 // scan the bitmap for the transparent colour and set
667 // the corresponding pixels in the mask to BLACK and
668 // the rest to WHITE
669 COLORREF vMaskColour = OS2RGB(rColour.Red(), rColour.Green(), rColour.Blue());
670
671 vHeader.cbFix = sizeof(vHeader);
672 vHeader.cx = (USHORT)rBitmap.GetWidth();
673 vHeader.cy = (USHORT)rBitmap.GetHeight();
674 vHeader.cPlanes = 1;
675 vHeader.cBitCount = 1;
676
677 m_hMaskBitmap = (WXHBITMAP) ::GpiCreateBitmap( m_hPs
678 ,&vHeader
679 ,0L
680 ,NULL
681 ,NULL
682 );
683
684 HPS srcPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
685 ::GpiSetBitmap(srcPS, (HBITMAP)rBitmap.GetHBITMAP());
686 HPS destPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
687 ::GpiSetBitmap(srcPS, (HBITMAP)m_hMaskBitmap);
688
689 // this is not very efficient, but I can't think
690 // of a better way of doing it
691 for (int w = 0; w < rBitmap.GetWidth(); w++)
692 {
693 for (int h = 0; h < rBitmap.GetHeight(); h++)
694 {
695 POINTL vPoint;
696
697 vPoint.x = w;
698 vPoint.y = h;
699
700 COLORREF col = ::GpiQueryPel(srcPS, &vPoint);
701
702 if (col == vMaskColour)
703 {
704 ::GpiSetColor(destPS, CLR_WHITE);
705 ::GpiSetPel(destPS, &vPoint);
706 }
707 else
708 {
709 ::GpiSetColor(destPS, CLR_BLACK);
710 ::GpiSetPel(destPS, &vPoint);
711 }
712 }
713 }
714 ::GpiDestroyPS(srcPS);
715 ::GpiDestroyPS(destPS);
716 return(TRUE);
717}
718
719// ----------------------------------------------------------------------------
720// wxBitmapHandler
721// ----------------------------------------------------------------------------
722
723bool wxBitmapHandler::Create(
724 wxGDIImage* pImage
725, void* pData
726, long lFlags
727, int nWidth
728, int nHeight
729, int nDepth
730)
731{
732 wxBitmap* pBitmap = wxDynamicCast( pImage
733 ,wxBitmap
734 );
735
736 return(pBitmap ? Create( pBitmap
737 ,pData
738 ,nWidth
739 ,nHeight
740 ,nDepth
741 ) : FALSE);
742}
743
744bool wxBitmapHandler::Load(
745 wxGDIImage* pImage
746, const wxString& rName
747, long lFlags
748, int nWidth
749, int nHeight
750)
751{
752 wxBitmap* pBitmap = wxDynamicCast( pImage
753 ,wxBitmap
754 );
755
756 return(pBitmap ? LoadFile( pBitmap
757 ,rName
758 ,lFlags
759 ,nWidth
760 ,nHeight
761 ) : FALSE);
762}
763
764bool wxBitmapHandler::Save(
765 wxGDIImage* pImage
766, const wxString& rName
767, int lType
768)
769{
770 wxBitmap* pBitmap = wxDynamicCast( pImage
771 ,wxBitmap
772 );
773
774 return(pBitmap ? SaveFile( pBitmap
775 ,rName
776 ,lType
777 ) : FALSE);
778}
779
780bool wxBitmapHandler::Create(
781 wxBitmap* WXUNUSED(pBitmap)
782, void* WXUNUSED(pData)
783, long WXUNUSED(lType)
784, int WXUNUSED(nWidth)
785, int WXUNUSED(nHeight)
786, int WXUNUSED(nDepth)
787)
788{
789 return(FALSE);
790}
791
792bool wxBitmapHandler::LoadFile(
793 wxBitmap* WXUNUSED(pBitmap)
794, const wxString& WXUNUSED(rName)
795, long WXUNUSED(lType)
796, int WXUNUSED(nDesiredWidth)
797, int WXUNUSED(nDesiredHeight)
798)
799{
800 return(FALSE);
801}
802
803bool wxBitmapHandler::SaveFile(
804 wxBitmap* WXUNUSED(pBitmap)
805, const wxString& WXUNUSED(rName)
806, int WXUNUSED(nType)
807, const wxPalette* WXUNUSED(pPalette)
808)
809{
810 return(FALSE);
811}
812