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