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