Fix Ok/IsOk() mess in wxGDIObject-derived classes; also added
[wxWidgets.git] / src / os2 / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/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 #include "wx/bitmap.h"
16
17 #ifndef WX_PRECOMP
18 #include <stdio.h>
19
20 #include "wx/list.h"
21 #include "wx/utils.h"
22 #include "wx/app.h"
23 #include "wx/palette.h"
24 #include "wx/dcmemory.h"
25 #include "wx/icon.h"
26 #include "wx/log.h"
27 #include "wx/image.h"
28 #endif
29
30 #include "wx/os2/private.h"
31
32 #include "wx/xpmdecod.h"
33
34 // ----------------------------------------------------------------------------
35 // macros
36 // ----------------------------------------------------------------------------
37
38 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
39 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
40
41 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
42
43 // ============================================================================
44 // implementation
45 // ============================================================================
46
47 // ----------------------------------------------------------------------------
48 // wxBitmapRefData
49 // ----------------------------------------------------------------------------
50
51 wxBitmapRefData::wxBitmapRefData()
52 {
53 m_nQuality = 0;
54 m_pSelectedInto = NULL;
55 m_nNumColors = 0;
56 m_pBitmapMask = NULL;
57 m_hBitmap = (WXHBITMAP) NULL;
58 } // end of wxBitmapRefData::wxBitmapRefData
59
60 wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData &tocopy)
61 {
62 m_nQuality = tocopy.m_nQuality;
63 m_pSelectedInto = NULL; // don't copy this
64 m_nNumColors = tocopy.m_nNumColors;
65
66 // copy the mask
67 if (tocopy.m_pBitmapMask)
68 m_pBitmapMask = new wxMask(*tocopy.m_pBitmapMask);
69
70 m_hBitmap = wxCopyBmp(tocopy.m_hBitmap);
71 }
72
73 void wxBitmapRefData::Free()
74 {
75 if ( m_pSelectedInto )
76 {
77 wxLogLastError(wxT("GpiDeleteBitmap(hbitmap)"));
78 }
79 if (m_hBitmap)
80 {
81 if (!::GpiDeleteBitmap((HBITMAP)m_hBitmap))
82 {
83 wxLogLastError(wxT("GpiDeleteBitmap(hbitmap)"));
84 }
85 }
86 if (m_pBitmapMask)
87 {
88 delete m_pBitmapMask;
89 m_pBitmapMask = NULL;
90 }
91 } // end of wxBitmapRefData::Free
92
93 // ----------------------------------------------------------------------------
94 // wxBitmap creation
95 // ----------------------------------------------------------------------------
96
97 wxGDIRefData* wxBitmap::CreateGDIRefData() const
98 {
99 return new wxBitmapRefData;
100 }
101
102 wxGDIRefData* wxBitmap::CloneGDIRefData(const wxGDIRefData* data) const
103 {
104 return new wxBitmapRefData(*wx_static_cast(const wxBitmapRefData *, data));
105 }
106
107 // this function should be called from all wxBitmap ctors
108 void wxBitmap::Init()
109 {
110 m_bIsMono = false;
111 //
112 // True for all bitmaps created from bits, wxImages, Xpms
113 //
114 } // end of wxBitmap::Init
115
116 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& rIcon)
117 {
118 HPOINTER hIcon = (HPOINTER)rIcon.GetHandle();
119 POINTERINFO SIconInfo;
120
121 if (!::WinQueryPointerInfo(hIcon, &SIconInfo))
122 {
123 wxLogLastError(wxT("WinQueryPointerInfo"));
124 return false;
125 }
126 wxBitmapRefData* pRefData = new wxBitmapRefData;
127
128 m_refData = pRefData;
129
130 int nWidth = rIcon.GetWidth();
131 int nHeight = rIcon.GetHeight();
132
133 pRefData->m_nWidth = nWidth;
134 pRefData->m_nHeight = nHeight;
135 pRefData->m_nDepth = wxDisplayDepth();
136
137 pRefData->m_hBitmap = (WXHBITMAP)SIconInfo.hbmColor;
138
139 wxMask* pMask = new wxMask(SIconInfo.hbmPointer);
140
141 pMask->SetMaskBitmap(GetHBITMAP());
142 SetMask(pMask);
143
144 return true;
145 } // end of wxBitmap::CopyFromIconOrCursor
146
147 bool wxBitmap::CopyFromCursor(
148 const wxCursor& rCursor
149 )
150 {
151 UnRef();
152
153 if (!rCursor.Ok())
154 return(false);
155 return(CopyFromIconOrCursor(rCursor));
156 } // end of wxBitmap::CopyFromCursor
157
158 bool wxBitmap::CopyFromIcon(
159 const wxIcon& rIcon
160 )
161 {
162 UnRef();
163
164 if (!rIcon.Ok())
165 return(false);
166
167 return CopyFromIconOrCursor(rIcon);
168 } // end of wxBitmap::CopyFromIcon
169
170 wxBitmap::~wxBitmap()
171 {
172 } // end of wxBitmap::~wxBitmap
173
174 wxBitmap::wxBitmap(
175 const char zBits[]
176 , int nWidth
177 , int nHeight
178 , int nDepth
179 )
180 {
181 Init();
182
183 wxBitmapRefData* pRefData = new wxBitmapRefData;
184 BITMAPINFOHEADER2 vHeader;
185 BITMAPINFO2 vInfo;
186 HDC hDc;
187 HPS hPs;
188 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
189 SIZEL vSize = {0, 0};
190 char* pzData;
191
192 wxASSERT(vHabmain != NULL);
193
194 m_refData = pRefData;
195
196 pRefData->m_nWidth = nWidth;
197 pRefData->m_nHeight = nHeight;
198 pRefData->m_nDepth = nDepth;
199 pRefData->m_nNumColors = 0;
200 pRefData->m_pSelectedInto = NULL;
201
202 hDc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
203 hPs = ::GpiCreatePS(vHabmain, hDc, &vSize, GPIA_ASSOC | PU_PELS);
204 if (hPs == 0)
205 {
206 wxLogLastError(wxT("GpiCreatePS Failure"));
207 }
208
209 if (nDepth == 1)
210 {
211 //
212 // We assume that it is in XBM format which is not quite the same as
213 // the format CreateBitmap() wants because the order of bytes in the
214 // line is reversed!
215 //
216 const size_t nBytesPerLine = (nWidth + 7) / 8;
217 const size_t nPadding = nBytesPerLine % 2;
218 const size_t nLen = nHeight * (nPadding + nBytesPerLine);
219 const char* pzSrc = zBits;
220 int nRows;
221 size_t nCols;
222
223 pzData = (char *)malloc(nLen);
224
225 char* pzDst = pzData;
226
227 for (nRows = 0; nRows < nHeight; nRows++)
228 {
229 for (nCols = 0; nCols < nBytesPerLine; nCols++)
230 {
231 unsigned char ucVal = *pzSrc++;
232 unsigned char ucReversed = 0;
233 int nBits;
234
235 for (nBits = 0; nBits < 8; nBits++)
236 {
237 ucReversed <<= 1;
238 ucReversed = (unsigned char)(ucReversed | (ucVal & 0x01));
239 ucVal >>= 1;
240 }
241 *pzDst++ = ucReversed;
242 }
243 if (nPadding)
244 *pzDst++ = 0;
245 }
246 }
247 else
248 {
249 //
250 // Bits should already be in Windows standard format
251 //
252 pzData = (char *)zBits; // const_cast is harmless
253 }
254
255 if (nDepth > 24)
256 nDepth = 24; // MAX supported in PM
257 memset(&vHeader, '\0', 16);
258 vHeader.cbFix = 16;
259 vHeader.cx = (USHORT)nWidth;
260 vHeader.cy = (USHORT)nHeight;
261 vHeader.cPlanes = 1L;
262 vHeader.cBitCount = (USHORT)nDepth;
263 vHeader.usReserved = 0;
264
265 memset(&vInfo, '\0', 16);
266 vInfo.cbFix = 16;
267 vInfo.cx = (USHORT)nWidth;
268 vInfo.cy = (USHORT)nHeight;
269 vInfo.cPlanes = 1L;
270 vInfo.cBitCount = (USHORT)nDepth;
271
272 HBITMAP hBmp = ::GpiCreateBitmap(hPs, &vHeader, CBM_INIT, (PBYTE)pzData, &vInfo);
273
274 if (!hBmp)
275 {
276 wxLogLastError(wxT("CreateBitmap"));
277 }
278 ::GpiDestroyPS(hPs);
279 ::DevCloseDC(hDc);
280 SetHBITMAP((WXHBITMAP)hBmp);
281 } // end of wxBitmap::wxBitmap
282
283 wxBitmap::wxBitmap(
284 int nW
285 , int nH
286 , int nD
287 )
288 {
289 Init();
290 (void)Create( nW
291 ,nH
292 ,nD
293 );
294 } // end of wxBitmap::wxBitmap
295
296 wxBitmap::wxBitmap(
297 const void* pData
298 , long lType
299 , int nWidth
300 , int nHeight
301 , int nDepth
302 )
303 {
304 Init();
305
306 (void)Create( pData
307 ,lType
308 ,nWidth
309 ,nHeight
310 ,nDepth
311 );
312 } // end of wxBitmap::wxBitmap
313
314 wxBitmap::wxBitmap(
315 int nId
316 , long lType
317 )
318 {
319 Init();
320 LoadFile( nId
321 ,(int)lType
322 );
323 SetId(nId);
324 } // end of wxBitmap::wxBitmap
325
326 bool wxBitmap::Create(
327 int nW
328 , int nH
329 , int nD
330 )
331 {
332 HBITMAP hBmp;
333 BITMAPINFOHEADER2 vHeader;
334
335 wxASSERT(vHabmain != NULL);
336 UnRef();
337 m_refData = new wxBitmapRefData;
338 GetBitmapData()->m_nWidth = nW;
339 GetBitmapData()->m_nHeight = nH;
340 GetBitmapData()->m_nDepth = nD;
341
342 //
343 // Xpms and bitmaps from other images can also be mono's, but only
344 // mono's need help changing their colors with MemDC changes
345 //
346 if (nD > 0)
347 {
348 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
349 SIZEL vSize = {0, 0};
350 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
351 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
352
353 if (nD == 1)
354 m_bIsMono = true;
355 memset(&vHeader, '\0', 16);
356 vHeader.cbFix = 16;
357 vHeader.cx = nW;
358 vHeader.cy = nH;
359 vHeader.cPlanes = 1;
360 vHeader.cBitCount = 24; //nD;
361
362 hBmp = ::GpiCreateBitmap( hPS
363 ,&vHeader
364 ,0L
365 ,NULL
366 ,NULL
367 );
368 ::GpiDestroyPS(hPS);
369 ::DevCloseDC(hDC);
370 }
371 else
372 {
373 HPS hPSScreen;
374 HDC hDCScreen;
375 LONG lBitCount;
376
377 hPSScreen = ::WinGetScreenPS(HWND_DESKTOP);
378 hDCScreen = ::GpiQueryDevice(hPSScreen);
379 ::DevQueryCaps(hDCScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitCount);
380
381 if (lBitCount > 24)
382 lBitCount = 24;
383
384 memset(&vHeader, '\0', 16);
385 vHeader.cbFix = 16;
386 vHeader.cx = nW;
387 vHeader.cy = nH;
388 vHeader.cPlanes = 1;
389 vHeader.cBitCount = (USHORT)lBitCount;
390
391 hBmp = ::GpiCreateBitmap( hPSScreen
392 ,&vHeader
393 ,0L
394 ,NULL
395 ,NULL
396 );
397
398 GetBitmapData()->m_nDepth = wxDisplayDepth();
399 ::WinReleasePS(hPSScreen);
400 }
401 SetHBITMAP((WXHBITMAP)hBmp);
402
403 return Ok();
404 } // end of wxBitmap::Create
405
406 bool wxBitmap::LoadFile(const wxString& filename, long type)
407 {
408 UnRef();
409
410 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
411
412 if ( handler )
413 {
414 m_refData = new wxBitmapRefData;
415
416 return handler->LoadFile(this, filename, type, -1, -1);
417 }
418 #if wxUSE_IMAGE
419 else // no bitmap handler found
420 {
421 wxImage image;
422 if ( image.LoadFile( filename, type ) && image.Ok() )
423 {
424 *this = wxBitmap(image);
425
426 return true;
427 }
428 }
429 #endif // wxUSE_IMAGE
430
431 return false;
432 }
433
434 bool wxBitmap::LoadFile(
435 int nId
436 , long lType
437 )
438 {
439 UnRef();
440
441 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
442 ,wxBitmapHandler
443 );
444
445 if (pHandler)
446 {
447 m_refData = new wxBitmapRefData;
448
449 return(pHandler->LoadFile( this
450 ,nId
451 ,lType
452 , -1
453 , -1
454 ));
455 }
456 else
457 {
458 return false;
459 }
460 } // end of wxBitmap::LoadFile
461
462 bool wxBitmap::Create(
463 const void* pData
464 , long lType
465 , int nWidth
466 , int nHeight
467 , int nDepth
468 )
469 {
470 UnRef();
471
472 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
473 ,wxBitmapHandler
474 );
475
476 if (!pHandler)
477 {
478 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %ld defined."), lType);
479
480 return false;
481 }
482
483 m_refData = new wxBitmapRefData;
484
485 return(pHandler->Create( this
486 ,pData
487 ,lType
488 ,nWidth
489 ,nHeight
490 ,nDepth
491 ));
492 } // end of wxBitmap::Create
493
494 bool wxBitmap::SaveFile(
495 const wxString& rFilename
496 , int lType
497 , const wxPalette* pPalette
498 )
499 {
500 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
501 ,wxBitmapHandler
502 );
503
504 if (pHandler)
505 {
506 return pHandler->SaveFile( this
507 ,rFilename
508 ,lType
509 ,pPalette
510 );
511 }
512 else
513 {
514 // FIXME what about palette? shouldn't we use it?
515 wxImage vImage = ConvertToImage();
516
517 if (!vImage.Ok())
518 return false;
519
520 return(vImage.SaveFile( rFilename
521 ,lType
522 ));
523 }
524 } // end of wxBitmap::SaveFile
525
526
527 // ----------------------------------------------------------------------------
528 // wxImage-wxBitmap conversion
529 // ----------------------------------------------------------------------------
530
531 bool wxBitmap::CreateFromImage (
532 const wxImage& rImage
533 , int nDepth
534 )
535 {
536 wxCHECK_MSG(rImage.Ok(), false, wxT("invalid image"));
537 m_refData = new wxBitmapRefData();
538
539 int nSizeLimit = 1024 * 768 * 3;
540 int nWidth = rImage.GetWidth();
541 int nBmpHeight = rImage.GetHeight();
542 int nBytePerLine = nWidth * 3;
543 int nSizeDWORD = sizeof(DWORD);
544 int nLineBoundary = nBytePerLine % nSizeDWORD;
545 int nPadding = 0;
546
547 if (nLineBoundary > 0)
548 {
549 nPadding = nSizeDWORD - nLineBoundary;
550 nBytePerLine += nPadding;
551 }
552
553 //
554 // Calc the number of DIBs and heights of DIBs
555 //
556 int nNumDIB = 1;
557 int nHRemain = 0;
558 int nHeight = nSizeLimit / nBytePerLine;
559
560 if (nHeight >= nBmpHeight)
561 nHeight = nBmpHeight;
562 else
563 {
564 nNumDIB = nBmpHeight / nHeight;
565 nHRemain = nBmpHeight % nHeight;
566 if (nHRemain > 0)
567 nNumDIB++;
568 }
569
570 //
571 // Set bitmap parameters
572 //
573 wxCHECK_MSG(rImage.Ok(), false, wxT("invalid image"));
574 SetWidth(nWidth);
575 SetHeight(nBmpHeight);
576 if (nDepth == 1)
577 m_bIsMono = true;
578 else
579 m_bIsMono = false;
580 if (nDepth == -1)
581 nDepth = wxDisplayDepth();
582 SetDepth(nDepth);
583
584 #if wxUSE_PALETTE
585 //
586 // Copy the palette from the source image
587 //
588 SetPalette(rImage.GetPalette());
589 #endif // wxUSE_PALETTE
590
591 //
592 // Create a DIB header
593 //
594 BITMAPINFOHEADER2 vHeader;
595 BITMAPINFO2 vInfo;
596
597 //
598 // Fill in the DIB header
599 //
600 memset(&vHeader, '\0', 16);
601 vHeader.cbFix = 16;
602 vHeader.cx = (ULONG)nWidth;
603 vHeader.cy = (ULONG)nHeight;
604 vHeader.cPlanes = 1L;
605 vHeader.cBitCount = 24;
606
607 //
608 // Memory for DIB data
609 //
610 unsigned char* pucBits;
611
612 pucBits = (unsigned char *)malloc(nBytePerLine * nHeight);
613 if(!pucBits)
614 {
615 wxFAIL_MSG(wxT("could not allocate memory for DIB"));
616 return false;
617 }
618 memset(pucBits, '\0', (nBytePerLine * nHeight));
619
620 //
621 // Create and set the device-dependent bitmap
622 //
623 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
624 SIZEL vSize = {0, 0};
625 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
626 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
627 LONG lScans;
628 HDC hDCScreen = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
629 HPS hPSScreen;
630 HBITMAP hBmp;
631 HBITMAP hBmpOld;
632
633 memset(&vInfo, '\0', 16);
634 vInfo.cbFix = 16;
635 vInfo.cx = (ULONG)nWidth;
636 vInfo.cy = (ULONG)nHeight;
637 vInfo.cPlanes = 1;
638 vInfo.cBitCount = 24; // Set to desired count going in
639
640 hBmp = ::GpiCreateBitmap( hPS
641 ,&vHeader
642 ,0L
643 ,NULL
644 ,NULL
645 );
646 #if wxUSE_PALETTE
647 HPAL hOldPalette = NULLHANDLE;
648 if (rImage.GetPalette().Ok())
649 {
650 hOldPalette = ::GpiSelectPalette(hPS, (HPAL)rImage.GetPalette().GetHPALETTE());
651 }
652 #endif // wxUSE_PALETTE
653
654 //
655 // Copy image data into DIB data and then into DDB (in a loop)
656 //
657 unsigned char* pData = rImage.GetData();
658 int i;
659 int j;
660 int n;
661 int nOrigin = 0;
662 unsigned char* ptdata = pData;
663 unsigned char* ptbits;
664
665 if ((hBmpOld = ::GpiSetBitmap(hPS, hBmp)) == HBM_ERROR)
666 {
667 ERRORID vError;
668 wxString sError;
669
670 vError = ::WinGetLastError(vHabmain);
671 sError = wxPMErrorToStr(vError);
672 }
673 for (n = 0; n < nNumDIB; n++)
674 {
675 if (nNumDIB > 1 && n == nNumDIB - 1 && nHRemain > 0)
676 {
677 //
678 // Redefine height and size of the (possibly) last smaller DIB
679 // memory is not reallocated
680 //
681 nHeight = nHRemain;
682 vHeader.cy = (DWORD)(nHeight);
683 vHeader.cbImage = nBytePerLine * nHeight;
684 }
685 ptbits = pucBits;
686 for (j = 0; j < nHeight; j++)
687 {
688 for (i = 0; i < nWidth; i++)
689 {
690 *(ptbits++) = *(ptdata + 2);
691 *(ptbits++) = *(ptdata + 1);
692 *(ptbits++) = *(ptdata);
693 ptdata += 3;
694 }
695 for (i = 0; i < nPadding; i++)
696 *(ptbits++) = 0;
697 }
698
699 //
700 // Have to do something similar to WIN32's StretchDIBits, use GpiBitBlt
701 // in combination with setting the bits into the selected bitmap
702 //
703 if ((lScans = ::GpiSetBitmapBits( hPS
704 ,0 // Start at the bottom
705 ,(LONG)nHeight // One line per scan
706 ,(PBYTE)pucBits
707 ,&vInfo
708 )) == GPI_ALTERROR)
709 {
710 ERRORID vError;
711 wxString sError;
712
713 vError = ::WinGetLastError(vHabmain);
714 sError = wxPMErrorToStr(vError);
715 }
716 hPSScreen = ::GpiCreatePS( vHabmain
717 ,hDCScreen
718 ,&vSize
719 ,PU_PELS | GPIA_ASSOC
720 );
721
722 POINTL vPoint[4] = { {0, nOrigin},
723 {nWidth, nHeight},
724 {0, 0}, {nWidth, nHeight}
725 };
726
727
728 ::GpiBitBlt( hPSScreen
729 ,hPS
730 ,4
731 ,vPoint
732 ,ROP_SRCCOPY
733 ,BBO_IGNORE
734 );
735 ::GpiDestroyPS(hPSScreen);
736 nOrigin += nHeight;
737 }
738 SetHBITMAP((WXHBITMAP)hBmp);
739 #if wxUSE_PALETTE
740 if (hOldPalette)
741 ::GpiSelectPalette(hPS, hOldPalette);
742 #endif // wxUSE_PALETTE
743
744 //
745 // Similarly, created an mono-bitmap for the possible mask
746 //
747 if (rImage.HasMask())
748 {
749 vHeader.cbFix = 16;
750 vHeader.cx = nWidth;
751 vHeader.cy = nHeight;
752 vHeader.cPlanes = 1;
753 vHeader.cBitCount = 24;
754 hBmp = ::GpiCreateBitmap( hPS
755 ,&vHeader
756 ,0L
757 ,NULL
758 ,NULL
759 );
760 hBmpOld = ::GpiSetBitmap(hPS, hBmp);
761 if (nNumDIB == 1)
762 nHeight = nBmpHeight;
763 else
764 nHeight = nSizeLimit / nBytePerLine;
765 vHeader.cy = (DWORD)(nHeight);
766 nOrigin = 0;
767
768 unsigned char cRed = rImage.GetMaskRed();
769 unsigned char cGreen = rImage.GetMaskGreen();
770 unsigned char cBlue = rImage.GetMaskBlue();
771 unsigned char cZero = 0;
772 unsigned char cOne = 255;
773
774 ptdata = pData;
775 for (n = 0; n < nNumDIB; n++)
776 {
777 if (nNumDIB > 1 && n == nNumDIB - 1 && nHRemain > 0)
778 {
779 //
780 // Redefine height and size of the (possibly) last smaller DIB
781 // memory is not reallocated
782 //
783 nHeight = nHRemain;
784 vHeader.cy = (DWORD)(nHeight);
785 vHeader.cbImage = nBytePerLine * nHeight;
786 }
787 ptbits = pucBits;
788 for (int j = 0; j < nHeight; j++)
789 {
790 for (i = 0; i < nWidth; i++)
791 {
792 unsigned char cRedImage = (*(ptdata++)) ;
793 unsigned char cGreenImage = (*(ptdata++)) ;
794 unsigned char cBlueImage = (*(ptdata++)) ;
795
796 if ((cRedImage != cRed) || (cGreenImage != cGreen) || (cBlueImage != cBlue))
797 {
798 *(ptbits++) = cOne;
799 *(ptbits++) = cOne;
800 *(ptbits++) = cOne;
801 }
802 else
803 {
804 *(ptbits++) = cZero;
805 *(ptbits++) = cZero;
806 *(ptbits++) = cZero;
807 }
808 }
809 for (i = 0; i < nPadding; i++)
810 *(ptbits++) = cZero;
811 }
812 lScans = ::GpiSetBitmapBits( hPS
813 ,0 // Start at the bottom
814 ,(LONG)nHeight // One line per scan
815 ,(PBYTE)pucBits
816 ,&vInfo
817 );
818 hPSScreen = ::GpiCreatePS( vHabmain
819 ,hDCScreen
820 ,&vSize
821 ,PU_PELS | GPIA_ASSOC
822 );
823 POINTL vPoint2[4] = { {0, nOrigin},
824 {nWidth, nHeight},
825 {0, 0}, {nWidth, nHeight}
826 };
827 ::GpiBitBlt( hPSScreen
828 ,hPS
829 ,4
830 ,vPoint2
831 ,ROP_SRCCOPY
832 ,BBO_IGNORE
833 );
834 ::GpiDestroyPS(hPSScreen);
835 nOrigin += nHeight;
836 }
837
838 //
839 // Create a wxMask object
840 //
841 wxMask* pMask = new wxMask();
842
843 pMask->SetMaskBitmap((WXHBITMAP)hBmp);
844 SetMask(pMask);
845 hBmpOld = ::GpiSetBitmap(hPS, hBmpOld);
846 }
847
848 //
849 // Free allocated resources
850 //
851 ::GpiSetBitmap(hPS, NULLHANDLE);
852 ::GpiDestroyPS(hPS);
853 ::DevCloseDC(hDCScreen);
854 ::DevCloseDC(hDC);
855 free(pucBits);
856 return true;
857 } // end of wxBitmap::CreateFromImage
858
859 wxImage wxBitmap::ConvertToImage() const
860 {
861 wxImage vImage;
862 wxDC* pDC;
863
864 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
865
866 //
867 // Create an wxImage object
868 //
869 int nWidth = GetWidth();
870 int nHeight = GetHeight();
871 int nDevWidth;
872 int nDevHeight;
873 int nBytePerLine = nWidth * 3;
874 int nSizeDWORD = sizeof(DWORD);
875 int nLineBoundary = nBytePerLine % nSizeDWORD;
876 int nPadding = 0;
877 unsigned char* pData;
878 unsigned char* lpBits;
879 long lScans;
880 BITMAPINFOHEADER2 vDIBh;
881 BITMAPINFO2 vDIBInfo;
882 HPS hPSMem;
883 HBITMAP hBitmap;
884 HBITMAP hOldBitmap;
885 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
886 SIZEL vSizlPage = {0,0};
887 HDC hDCMem = NULLHANDLE;
888
889 vImage.Create( nWidth
890 ,nHeight
891 );
892 pData = vImage.GetData();
893 if(!pData)
894 {
895 wxFAIL_MSG( wxT("could not allocate data for image") );
896 return wxNullImage;
897 }
898 if(nLineBoundary > 0)
899 {
900 nPadding = nSizeDWORD - nLineBoundary;
901 nBytePerLine += nPadding;
902 }
903 wxDisplaySize( &nDevWidth
904 ,&nDevHeight
905 );
906 //
907 // Create and fill a DIB header
908 //
909 memset(&vDIBh, '\0', 16);
910 vDIBh.cbFix = 16;
911 vDIBh.cx = nWidth;
912 vDIBh.cy = nHeight;
913 vDIBh.cPlanes = 1;
914 vDIBh.cBitCount = 24;
915
916 memset(&vDIBInfo, '\0', 16);
917 vDIBInfo.cbFix = 16;
918 vDIBInfo.cx = nWidth;
919 vDIBInfo.cy = nHeight;
920 vDIBInfo.cPlanes = 1;
921 vDIBInfo.cBitCount = 24;
922
923 lpBits = (unsigned char *)malloc(nBytePerLine * nHeight);
924 if (!lpBits)
925 {
926 wxFAIL_MSG(wxT("could not allocate data for DIB"));
927 free(pData);
928 return wxNullImage;
929 }
930 memset(lpBits, '\0', (nBytePerLine * nHeight));
931 hBitmap = (HBITMAP)GetHBITMAP();
932
933 //
934 // May already be selected into a PS
935 //
936 if ((pDC = GetSelectedInto()) != NULL)
937 {
938 hPSMem = pDC->GetHPS();
939 }
940 else
941 {
942 hDCMem = ::DevOpenDC( vHabmain
943 ,OD_MEMORY
944 ,"*"
945 ,5L
946 ,(PDEVOPENDATA)&vDop
947 ,NULLHANDLE
948 );
949 hPSMem = ::GpiCreatePS( vHabmain
950 ,hDCMem
951 ,&vSizlPage
952 ,PU_PELS | GPIA_ASSOC
953 );
954 }
955 if ((hOldBitmap = ::GpiSetBitmap(hPSMem, hBitmap)) == HBM_ERROR)
956 {
957 ERRORID vError;
958 wxString sError;
959
960 vError = ::WinGetLastError(vHabmain);
961 sError = wxPMErrorToStr(vError);
962 }
963
964 //
965 // Copy data from the device-dependent bitmap to the DIB
966 //
967 if ((lScans = ::GpiQueryBitmapBits( hPSMem
968 ,0L
969 ,(LONG)nHeight
970 ,(PBYTE)lpBits
971 ,&vDIBInfo
972 )) == GPI_ALTERROR)
973 {
974 ERRORID vError;
975 wxString sError;
976
977 vError = ::WinGetLastError(vHabmain);
978 sError = wxPMErrorToStr(vError);
979 }
980
981 //
982 // Copy DIB data into the wxImage object
983 //
984 int i;
985 int j;
986 unsigned char* ptdata = pData;
987 unsigned char* ptbits = lpBits;
988
989 for (i = 0; i < nHeight; i++)
990 {
991 for (j = 0; j < nWidth; j++)
992 {
993 *(ptdata++) = *(ptbits+2);
994 *(ptdata++) = *(ptbits+1);
995 *(ptdata++) = *(ptbits );
996 ptbits += 3;
997 }
998 ptbits += nPadding;
999 }
1000 if ((pDC = GetSelectedInto()) == NULL)
1001 {
1002 ::GpiSetBitmap(hPSMem, NULLHANDLE);
1003 ::GpiDestroyPS(hPSMem);
1004 ::DevCloseDC(hDCMem);
1005 }
1006
1007 //
1008 // Similarly, set data according to the possible mask bitmap
1009 //
1010 if (GetMask() && GetMask()->GetMaskBitmap())
1011 {
1012 hBitmap = (HBITMAP)GetMask()->GetMaskBitmap();
1013
1014 //
1015 // Memory DC/PS created, color set, data copied, and memory DC/PS deleted
1016 //
1017 HDC hMemDC = ::DevOpenDC( vHabmain
1018 ,OD_MEMORY
1019 ,"*"
1020 ,5L
1021 ,(PDEVOPENDATA)&vDop
1022 ,NULLHANDLE
1023 );
1024 HPS hMemPS = ::GpiCreatePS( vHabmain
1025 ,hMemDC
1026 ,&vSizlPage
1027 ,PU_PELS | GPIA_ASSOC
1028 );
1029 ::GpiSetColor(hMemPS, OS2RGB(0, 0, 0));
1030 ::GpiSetBackColor(hMemPS, OS2RGB(255, 255, 255) );
1031 ::GpiSetBitmap(hMemPS, hBitmap);
1032 ::GpiQueryBitmapBits( hPSMem
1033 ,0L
1034 ,(LONG)nHeight
1035 ,(PBYTE)lpBits
1036 ,&vDIBInfo
1037 );
1038 ::GpiSetBitmap(hMemPS, NULLHANDLE);
1039 ::GpiDestroyPS(hMemPS);
1040 ::DevCloseDC(hMemDC);
1041
1042 //
1043 // Background color set to RGB(16,16,16) in consistent with wxGTK
1044 //
1045 unsigned char ucRed = 16;
1046 unsigned char ucGreen = 16;
1047 unsigned char ucBlue = 16;
1048
1049 ptdata = pData;
1050 ptbits = lpBits;
1051 for (i = 0; i < nHeight; i++)
1052 {
1053 for (j = 0; j < nWidth; j++)
1054 {
1055 if (*ptbits != 0)
1056 ptdata += 3;
1057 else
1058 {
1059 *(ptdata++) = ucRed;
1060 *(ptdata++) = ucGreen;
1061 *(ptdata++) = ucBlue;
1062 }
1063 ptbits += 3;
1064 }
1065 ptbits += nPadding;
1066 }
1067 vImage.SetMaskColour( ucRed
1068 ,ucGreen
1069 ,ucBlue
1070 );
1071 vImage.SetMask(true);
1072 }
1073 else
1074 {
1075 vImage.SetMask(false);
1076 }
1077
1078 //
1079 // Free allocated resources
1080 //
1081 free(lpBits);
1082 return vImage;
1083 } // end of wxBitmap::ConvertToImage
1084
1085 // ----------------------------------------------------------------------------
1086 // sub bitmap extraction
1087 // ----------------------------------------------------------------------------
1088
1089 wxBitmap wxBitmap::GetSubBitmap(
1090 const wxRect& rRect
1091 ) const
1092 {
1093 wxCHECK_MSG( Ok() &&
1094 (rRect.x >= 0) && (rRect.y >= 0) &&
1095 (rRect.x + rRect.width <= GetWidth()) &&
1096 (rRect.y + rRect.height <= GetHeight()),
1097 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
1098
1099 wxBitmap vRet( rRect.width
1100 ,rRect.height
1101 ,GetDepth()
1102 );
1103 wxASSERT_MSG( vRet.Ok(), wxT("GetSubBitmap error") );
1104
1105
1106 //
1107 // Copy bitmap data
1108 //
1109 SIZEL vSize = {0, 0};
1110 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1111 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1112 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1113 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1114 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1115 POINTL vPoint[4] = { {0, 0}, {rRect.width, rRect.height},
1116 {rRect.x, rRect.y},
1117 {rRect.x + rRect.width, rRect.y + rRect.height}
1118 };
1119
1120 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetHBITMAP());
1121 ::GpiSetBitmap(hPSDst, (HBITMAP) vRet.GetHBITMAP());
1122 ::GpiBitBlt( hPSDst
1123 ,hPSSrc
1124 ,4L
1125 ,vPoint
1126 ,ROP_SRCCOPY
1127 ,BBO_IGNORE
1128 );
1129
1130 //
1131 // Copy mask if there is one
1132 //
1133 if (GetMask())
1134 {
1135 BITMAPINFOHEADER2 vBmih;
1136
1137 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1138 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1139 vBmih.cx = rRect.width;
1140 vBmih.cy = rRect.height;
1141 vBmih.cPlanes = 1;
1142 vBmih.cBitCount = 24;
1143
1144 HBITMAP hBmpMask = ::GpiCreateBitmap( hPSDst
1145 ,&vBmih
1146 ,0L
1147 ,NULL
1148 ,NULL
1149 );
1150
1151 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetHBITMAP());
1152 ::GpiSetBitmap(hPSDst, (HBITMAP) vRet.GetHBITMAP());
1153
1154 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetMask()->GetMaskBitmap());
1155 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpMask);
1156 ::GpiBitBlt( hPSDst
1157 ,hPSSrc
1158 ,4L
1159 ,vPoint
1160 ,ROP_SRCCOPY
1161 ,BBO_IGNORE
1162 );
1163
1164 wxMask* pMask = new wxMask((WXHBITMAP)hBmpMask);
1165 vRet.SetMask(pMask);
1166 }
1167
1168 ::GpiSetBitmap(hPSSrc, NULL);
1169 ::GpiSetBitmap(hPSDst, NULL);
1170 ::GpiDestroyPS(hPSSrc);
1171 ::GpiDestroyPS(hPSDst);
1172 ::DevCloseDC(hDCSrc);
1173 ::DevCloseDC(hDCDst);
1174 return vRet;
1175 } // end of wxBitmap::GetSubBitmap
1176
1177 // ----------------------------------------------------------------------------
1178 // wxBitmap accessors
1179 // ----------------------------------------------------------------------------
1180
1181 void wxBitmap::SetQuality(
1182 int nQ
1183 )
1184 {
1185 EnsureHasData();
1186
1187 GetBitmapData()->m_nQuality = nQ;
1188 } // end of wxBitmap::SetQuality
1189
1190 void wxBitmap::SetPalette(
1191 const wxPalette& rPalette
1192 )
1193 {
1194 EnsureHasData();
1195
1196 GetBitmapData()->m_vBitmapPalette = rPalette;
1197 } // end of wxBitmap::SetPalette
1198
1199 void wxBitmap::SetMask(
1200 wxMask* pMask
1201 )
1202 {
1203 EnsureHasData();
1204
1205 GetBitmapData()->m_pBitmapMask = pMask;
1206 } // end of wxBitmap::SetMask
1207
1208 wxBitmap wxBitmap::GetBitmapForDC(wxDC& WXUNUSED(rDc)) const
1209 {
1210 return(*this);
1211 } // end of wxBitmap::GetBitmapForDC
1212
1213 // ----------------------------------------------------------------------------
1214 // wxMask
1215 // ----------------------------------------------------------------------------
1216
1217 wxMask::wxMask()
1218 {
1219 m_hMaskBitmap = 0;
1220 } // end of wxMask::wxMask
1221
1222 wxMask::wxMask(const wxMask& tocopy)
1223 {
1224 m_hMaskBitmap = wxCopyBmp(tocopy.m_hMaskBitmap);
1225 } // end of wxMask::wxMask
1226
1227 // Construct a mask from a bitmap and a colour indicating
1228 // the transparent area
1229 wxMask::wxMask(
1230 const wxBitmap& rBitmap
1231 , const wxColour& rColour
1232 )
1233 {
1234 m_hMaskBitmap = 0;
1235 Create( rBitmap
1236 ,rColour
1237 );
1238 } // end of wxMask::wxMask
1239
1240 // Construct a mask from a bitmap and a palette index indicating
1241 // the transparent area
1242 wxMask::wxMask(
1243 const wxBitmap& rBitmap
1244 , int nPaletteIndex
1245 )
1246 {
1247 m_hMaskBitmap = 0;
1248 Create( rBitmap
1249 ,nPaletteIndex
1250 );
1251 } // end of wxMask::wxMask
1252
1253 // Construct a mask from a mono bitmap (copies the bitmap).
1254 wxMask::wxMask(
1255 const wxBitmap& rBitmap
1256 )
1257 {
1258 m_hMaskBitmap = 0;
1259 Create(rBitmap);
1260 } // end of wxMask::wxMask
1261
1262 wxMask::~wxMask()
1263 {
1264 if (m_hMaskBitmap)
1265 ::GpiDeleteBitmap((HBITMAP)m_hMaskBitmap);
1266 } // end of wxMask::~wxMask
1267
1268 // Create a mask from a mono bitmap (copies the bitmap).
1269 bool wxMask::Create(
1270 const wxBitmap& rBitmap
1271 )
1272 {
1273 BITMAPINFOHEADER2 vBmih;
1274 SIZEL vSize = {0, 0};
1275 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1276 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1277 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1278 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1279 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1280 POINTL vPoint[4] = { {0 ,0}, {rBitmap.GetWidth(), rBitmap.GetHeight()},
1281 {0, 0}, {rBitmap.GetWidth(), rBitmap.GetHeight()}
1282 };
1283
1284 if (m_hMaskBitmap)
1285 {
1286 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1287 m_hMaskBitmap = 0;
1288 }
1289 if (!rBitmap.Ok() || rBitmap.GetDepth() != 1)
1290 {
1291 return false;
1292 }
1293
1294 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1295 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1296 vBmih.cx = rBitmap.GetWidth();
1297 vBmih.cy = rBitmap.GetHeight();
1298 vBmih.cPlanes = 1;
1299 vBmih.cBitCount = 24;
1300
1301 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
1302 ,&vBmih
1303 ,0L
1304 ,NULL
1305 ,NULL
1306 );
1307
1308 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
1309 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
1310 ::GpiBitBlt( hPSDst
1311 ,hPSSrc
1312 ,4L
1313 ,vPoint
1314 ,ROP_SRCCOPY
1315 ,BBO_IGNORE
1316 );
1317
1318 ::GpiDestroyPS(hPSSrc);
1319 ::GpiDestroyPS(hPSDst);
1320 ::DevCloseDC(hDCSrc);
1321 ::DevCloseDC(hDCDst);
1322 return true;
1323 } // end of wxMask::Create
1324
1325 // Create a mask from a bitmap and a palette index indicating
1326 // the transparent area
1327 bool wxMask::Create(
1328 const wxBitmap& rBitmap
1329 , int nPaletteIndex
1330 )
1331 {
1332 if (m_hMaskBitmap)
1333 {
1334 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1335 m_hMaskBitmap = 0;
1336 }
1337 if (rBitmap.Ok() && rBitmap.GetPalette()->Ok())
1338 {
1339 unsigned char cRed;
1340 unsigned char cGreen;
1341 unsigned char cBlue;
1342
1343 if (rBitmap.GetPalette()->GetRGB( nPaletteIndex
1344 ,&cRed
1345 ,&cGreen
1346 ,&cBlue
1347 ))
1348 {
1349 wxColour vTransparentColour( cRed
1350 ,cGreen
1351 ,cBlue
1352 );
1353
1354 return (Create( rBitmap
1355 ,vTransparentColour
1356 ));
1357 }
1358 }
1359 return false;
1360 } // end of wxMask::Create
1361
1362 // Create a mask from a bitmap and a colour indicating
1363 // the transparent area
1364 bool wxMask::Create(
1365 const wxBitmap& rBitmap
1366 , const wxColour& rColour
1367 )
1368 {
1369 bool bOk = true;
1370 COLORREF vMaskColour = OS2RGB( rColour.Red()
1371 ,rColour.Green()
1372 ,rColour.Blue()
1373 );
1374 BITMAPINFOHEADER2 vBmih;
1375 SIZEL vSize = {0, 0};
1376 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1377 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1378 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1379 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1380 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1381
1382 if (m_hMaskBitmap)
1383 {
1384 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1385 m_hMaskBitmap = 0;
1386 }
1387 if (!rBitmap.Ok())
1388 {
1389 return false;
1390 }
1391
1392 //
1393 // Scan the bitmap for the transparent colour and set
1394 // the corresponding pixels in the mask to BLACK and
1395 // the rest to WHITE
1396 //
1397
1398 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1399 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1400 vBmih.cx = rBitmap.GetWidth();
1401 vBmih.cy = rBitmap.GetHeight();
1402 vBmih.cPlanes = 1;
1403 vBmih.cBitCount = 1;
1404
1405 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
1406 ,&vBmih
1407 ,0L
1408 ,NULL
1409 ,NULL
1410 );
1411
1412 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
1413 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
1414
1415 //
1416 // This is not very efficient, but I can't think
1417 // of a better way of doing it
1418 //
1419 for (int w = 0; w < rBitmap.GetWidth(); w++)
1420 {
1421 for (int h = 0; h < rBitmap.GetHeight(); h++)
1422 {
1423 POINTL vPt = {w, h};
1424 COLORREF vCol = (COLORREF)::GpiQueryPel(hPSSrc, &vPt);
1425 if (vCol == (COLORREF)CLR_NOINDEX)
1426 {
1427 //
1428 // Doesn't make sense to continue
1429 //
1430 bOk = false;
1431 break;
1432 }
1433
1434 if (vCol == vMaskColour)
1435 {
1436 ::GpiSetColor(hPSDst, OS2RGB(0, 0, 0));
1437 ::GpiSetPel(hPSDst, &vPt);
1438 }
1439 else
1440 {
1441 ::GpiSetColor(hPSDst, OS2RGB(255, 255, 255));
1442 ::GpiSetPel(hPSDst, &vPt);
1443 }
1444 }
1445 }
1446 ::GpiSetBitmap(hPSSrc, NULL);
1447 ::GpiSetBitmap(hPSDst, NULL);
1448 ::GpiDestroyPS(hPSSrc);
1449 ::GpiDestroyPS(hPSDst);
1450 ::DevCloseDC(hDCSrc);
1451 ::DevCloseDC(hDCDst);
1452 return true;
1453 } // end of wxMask::Create
1454
1455 // ----------------------------------------------------------------------------
1456 // wxBitmapHandler
1457 // ----------------------------------------------------------------------------
1458
1459 bool wxBitmapHandler::Create( wxGDIImage* pImage,
1460 const void* pData,
1461 long WXUNUSED(lFlags),
1462 int nWidth,
1463 int nHeight,
1464 int nDepth)
1465 {
1466 wxBitmap* pBitmap = wxDynamicCast( pImage
1467 ,wxBitmap
1468 );
1469
1470 return(pBitmap ? Create( pBitmap
1471 ,pData
1472 ,nWidth
1473 ,nHeight
1474 ,nDepth
1475 ) : false);
1476 }
1477
1478 bool wxBitmapHandler::Load(
1479 wxGDIImage* pImage
1480 , int nId
1481 , long lFlags
1482 , int nWidth
1483 , int nHeight
1484 )
1485 {
1486 wxBitmap* pBitmap = wxDynamicCast( pImage
1487 ,wxBitmap
1488 );
1489
1490 return(pBitmap ? LoadFile( pBitmap
1491 ,nId
1492 ,lFlags
1493 ,nWidth
1494 ,nHeight
1495 ) : false);
1496 }
1497
1498 bool wxBitmapHandler::Save(
1499 wxGDIImage* pImage
1500 , const wxString& rName
1501 , int lType
1502 )
1503 {
1504 wxBitmap* pBitmap = wxDynamicCast( pImage
1505 ,wxBitmap
1506 );
1507
1508 return(pBitmap ? SaveFile( pBitmap
1509 ,rName
1510 ,lType
1511 ) : false);
1512 }
1513
1514 bool wxBitmapHandler::Create(
1515 wxBitmap* WXUNUSED(pBitmap)
1516 , const void* WXUNUSED(pData)
1517 , long WXUNUSED(lType)
1518 , int WXUNUSED(nWidth)
1519 , int WXUNUSED(nHeight)
1520 , int WXUNUSED(nDepth)
1521 )
1522 {
1523 return false;
1524 }
1525
1526 bool wxBitmapHandler::LoadFile(
1527 wxBitmap* WXUNUSED(pBitmap)
1528 , int WXUNUSED(nId)
1529 , long WXUNUSED(lType)
1530 , int WXUNUSED(nDesiredWidth)
1531 , int WXUNUSED(nDesiredHeight)
1532 )
1533 {
1534 return false;
1535 }
1536
1537 bool wxBitmapHandler::LoadFile(
1538 wxBitmap* WXUNUSED(pBitmap)
1539 , const wxString& WXUNUSED(rName)
1540 , long WXUNUSED(lType)
1541 , int WXUNUSED(nDesiredWidth)
1542 , int WXUNUSED(nDesiredHeight)
1543 )
1544 {
1545 return false;
1546 }
1547
1548 bool wxBitmapHandler::SaveFile(
1549 wxBitmap* WXUNUSED(pBitmap)
1550 , const wxString& WXUNUSED(rName)
1551 , int WXUNUSED(nType)
1552 , const wxPalette* WXUNUSED(pPalette)
1553 )
1554 {
1555 return false;
1556 }
1557
1558 // ----------------------------------------------------------------------------
1559 // Utility functions
1560 // ----------------------------------------------------------------------------
1561 HBITMAP wxInvertMask(
1562 HBITMAP hBmpMask
1563 , int nWidth
1564 , int nHeight
1565 )
1566 {
1567 HBITMAP hBmpInvMask = 0;
1568
1569 wxCHECK_MSG( hBmpMask, 0, _T("invalid bitmap in wxInvertMask") );
1570
1571 //
1572 // Get width/height from the bitmap if not given
1573 //
1574 if (!nWidth || !nHeight)
1575 {
1576 BITMAPINFOHEADER2 vBmhdr;
1577
1578 ::GpiQueryBitmapInfoHeader( hBmpMask
1579 ,&vBmhdr
1580 );
1581 nWidth = (int)vBmhdr.cx;
1582 nHeight = (int)vBmhdr.cy;
1583 }
1584
1585 BITMAPINFOHEADER2 vBmih;
1586 SIZEL vSize = {0, 0};
1587 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1588 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1589 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1590 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1591 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1592 POINTL vPoint[4] = { {0 ,0}, {nWidth, nHeight},
1593 {0, 0}, {nWidth, nHeight}
1594 };
1595
1596 memset(&vBmih, '\0', 16);
1597 vBmih.cbFix = 16;
1598 vBmih.cx = nWidth;
1599 vBmih.cy = nHeight;
1600 vBmih.cPlanes = 1;
1601 vBmih.cBitCount = 24;
1602
1603 hBmpInvMask = ::GpiCreateBitmap( hPSDst
1604 ,&vBmih
1605 ,0L
1606 ,NULL
1607 ,NULL
1608 );
1609
1610 ::GpiSetBitmap(hPSSrc, (HBITMAP) hBmpMask);
1611 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpInvMask);
1612
1613 ::GpiBitBlt( hPSDst
1614 ,hPSSrc
1615 ,4L
1616 ,vPoint
1617 ,ROP_SRCINVERT
1618 ,BBO_IGNORE
1619 );
1620
1621 ::GpiDestroyPS(hPSSrc);
1622 ::GpiDestroyPS(hPSDst);
1623 ::DevCloseDC(hDCSrc);
1624 ::DevCloseDC(hDCDst);
1625
1626 return hBmpInvMask;
1627 } // end of WxWinGdi_InvertMask
1628
1629 HBITMAP wxCopyBmp( HBITMAP hBmp, bool flip, int nWidth, int nHeight )
1630 {
1631 wxCHECK_MSG( hBmp, 0, _T("invalid bitmap in wxCopyBmp") );
1632
1633 //
1634 // Get width/height from the bitmap if not given
1635 //
1636 if (!nWidth || !nHeight)
1637 {
1638 BITMAPINFOHEADER2 vBmhdr;
1639
1640 vBmhdr.cbFix = 16;
1641 ::GpiQueryBitmapInfoHeader( hBmp,
1642 &vBmhdr );
1643 nWidth = (int)vBmhdr.cx;
1644 nHeight = (int)vBmhdr.cy;
1645 }
1646
1647 BITMAPINFOHEADER2 vBmih;
1648 SIZEL vSize = {0, 0};
1649 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1650 HDC hDCSrc = ::DevOpenDC( vHabmain,
1651 OD_MEMORY,
1652 "*",
1653 5L,
1654 (PDEVOPENDATA)&vDop,
1655 NULLHANDLE );
1656 HDC hDCDst = ::DevOpenDC( vHabmain,
1657 OD_MEMORY,
1658 "*",
1659 5L,
1660 (PDEVOPENDATA)&vDop,
1661 NULLHANDLE );
1662 HPS hPSSrc = ::GpiCreatePS( vHabmain,
1663 hDCSrc,
1664 &vSize,
1665 PU_PELS | GPIA_ASSOC );
1666 HPS hPSDst = ::GpiCreatePS( vHabmain,
1667 hDCDst,
1668 &vSize,
1669 PU_PELS | GPIA_ASSOC );
1670 POINTL vPoint[4] = { {0, nHeight},
1671 {nWidth, 0},
1672 {0, 0},
1673 {nWidth, nHeight} };
1674 if (!flip)
1675 {
1676 vPoint[0].y = 0;
1677 vPoint[1].y = nHeight;
1678 }
1679 memset(&vBmih, '\0', 16);
1680 vBmih.cbFix = 16;
1681 vBmih.cx = nWidth;
1682 vBmih.cy = nHeight;
1683 vBmih.cPlanes = 1;
1684 vBmih.cBitCount = 24;
1685
1686 HBITMAP hInvBmp = ::GpiCreateBitmap( hPSDst,
1687 &vBmih,
1688 0L,
1689 NULL,
1690 NULL );
1691
1692 ::GpiSetBitmap(hPSSrc, (HBITMAP) hBmp);
1693 ::GpiSetBitmap(hPSDst, (HBITMAP) hInvBmp);
1694
1695 ::GpiBitBlt( hPSDst,
1696 hPSSrc,
1697 4L,
1698 vPoint,
1699 ROP_SRCCOPY,
1700 BBO_IGNORE );
1701
1702 ::GpiDestroyPS(hPSSrc);
1703 ::GpiDestroyPS(hPSDst);
1704 ::DevCloseDC(hDCSrc);
1705 ::DevCloseDC(hDCDst);
1706
1707 return hInvBmp;
1708 } // end of wxFlipBmp