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