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