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