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