]> git.saurik.com Git - wxWidgets.git/blame - src/os2/bitmap.cpp
fixed memory leak in RestoreState
[wxWidgets.git] / src / os2 / bitmap.cpp
CommitLineData
0e320a79 1/////////////////////////////////////////////////////////////////////////////
8ecff181 2// Name: src/os2/bitmap.cpp
0e320a79 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
e4db172a
WS
15#include "wx/bitmap.h"
16
d88de032
DW
17#ifndef WX_PRECOMP
18 #include <stdio.h>
19
20 #include "wx/list.h"
21 #include "wx/utils.h"
22 #include "wx/app.h"
23 #include "wx/palette.h"
24 #include "wx/dcmemory.h"
d88de032 25 #include "wx/icon.h"
e4db172a 26 #include "wx/log.h"
155ecd4c 27 #include "wx/image.h"
0e320a79
DW
28#endif
29
d88de032 30#include "wx/os2/private.h"
0e320a79 31
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
cd7ff808
SN
60wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData &tocopy)
61{
62 m_nQuality = tocopy.m_nQuality;
63 m_pSelectedInto = NULL; // don't copy this
64 m_nNumColors = tocopy.m_nNumColors;
65
66 // copy the mask
67 if (tocopy.m_pBitmapMask)
68 m_pBitmapMask = new wxMask(*tocopy.m_pBitmapMask);
69
a4e15a8d 70 m_hBitmap = wxCopyBmp(tocopy.m_hBitmap);
cd7ff808
SN
71}
72
3b9e3455 73void wxBitmapRefData::Free()
0e320a79 74{
1d0edc0f
DW
75 if ( m_pSelectedInto )
76 {
2173b18f 77 wxLogLastError(wxT("GpiDeleteBitmap(hbitmap)"));
1d0edc0f 78 }
3b9e3455
DW
79 if (m_hBitmap)
80 {
3437f881 81 if (!::GpiDeleteBitmap((HBITMAP)m_hBitmap))
3b9e3455 82 {
2173b18f 83 wxLogLastError(wxT("GpiDeleteBitmap(hbitmap)"));
3b9e3455
DW
84 }
85 }
2590f154
DW
86 if (m_pBitmapMask)
87 {
88 delete m_pBitmapMask;
89 m_pBitmapMask = NULL;
90 }
341366c6 91} // end of wxBitmapRefData::Free
0e320a79 92
3b9e3455
DW
93// ----------------------------------------------------------------------------
94// wxBitmap creation
95// ----------------------------------------------------------------------------
0e320a79 96
cd7ff808
SN
97wxObjectRefData* wxBitmap::CreateRefData() const
98{
99 return new wxBitmapRefData;
100}
101
102wxObjectRefData* wxBitmap::CloneRefData(const wxObjectRefData* data) const
103{
104 return new wxBitmapRefData(*wx_static_cast(const wxBitmapRefData *, data));
105}
106
3b9e3455
DW
107// this function should be called from all wxBitmap ctors
108void wxBitmap::Init()
0e320a79 109{
d0ee33f5 110 m_bIsMono = false;
1c9a789e
DW
111 //
112 // True for all bitmaps created from bits, wxImages, Xpms
113 //
6f38c86f 114} // end of wxBitmap::Init
0e320a79 115
8ecff181 116bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& rIcon)
d88de032 117{
6f38c86f
DW
118 HPOINTER hIcon = (HPOINTER)rIcon.GetHandle();
119 POINTERINFO SIconInfo;
120
121 if (!::WinQueryPointerInfo(hIcon, &SIconInfo))
122 {
123 wxLogLastError(wxT("WinQueryPointerInfo"));
d0ee33f5 124 return false;
6f38c86f 125 }
3b9e3455 126 wxBitmapRefData* pRefData = new wxBitmapRefData;
d88de032 127
3b9e3455 128 m_refData = pRefData;
d88de032 129
6f38c86f
DW
130 int nWidth = rIcon.GetWidth();
131 int nHeight = rIcon.GetHeight();
d88de032 132
6f38c86f
DW
133 pRefData->m_nWidth = nWidth;
134 pRefData->m_nHeight = nHeight;
135 pRefData->m_nDepth = wxDisplayDepth();
d88de032 136
6f38c86f
DW
137 pRefData->m_hBitmap = (WXHBITMAP)SIconInfo.hbmColor;
138
16ff355b
DW
139 wxMask* pMask = new wxMask(SIconInfo.hbmPointer);
140
141 pMask->SetMaskBitmap(GetHBITMAP());
142 SetMask(pMask);
143
d0ee33f5 144 return true;
6f38c86f 145} // end of wxBitmap::CopyFromIconOrCursor
0e320a79 146
3b9e3455
DW
147bool wxBitmap::CopyFromCursor(
148 const wxCursor& rCursor
149)
d88de032 150{
3b9e3455 151 UnRef();
d88de032 152
3b9e3455 153 if (!rCursor.Ok())
d0ee33f5 154 return(false);
43543d98 155 return(CopyFromIconOrCursor(rCursor));
6f38c86f 156} // end of wxBitmap::CopyFromCursor
d88de032 157
3b9e3455
DW
158bool wxBitmap::CopyFromIcon(
159 const wxIcon& rIcon
160)
0e320a79 161{
3b9e3455 162 UnRef();
0e320a79 163
3b9e3455 164 if (!rIcon.Ok())
d0ee33f5 165 return(false);
0e320a79 166
43543d98 167 return CopyFromIconOrCursor(rIcon);
6f38c86f 168} // end of wxBitmap::CopyFromIcon
0e320a79 169
3b9e3455 170wxBitmap::~wxBitmap()
d88de032 171{
6f38c86f 172} // end of wxBitmap::~wxBitmap
d88de032 173
3b9e3455
DW
174wxBitmap::wxBitmap(
175 const char zBits[]
3437f881
DW
176, int nWidth
177, int nHeight
178, int nDepth
3b9e3455
DW
179)
180{
181 Init();
182
183 wxBitmapRefData* pRefData = new wxBitmapRefData;
184 BITMAPINFOHEADER2 vHeader;
185 BITMAPINFO2 vInfo;
186 HDC hDc;
187 HPS hPs;
43543d98 188 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3b9e3455 189 SIZEL vSize = {0, 0};
3437f881 190 char* pzData;
3b9e3455 191
43543d98 192 wxASSERT(vHabmain != NULL);
3b9e3455 193
3437f881 194 m_refData = pRefData;
3b9e3455 195
3437f881
DW
196 pRefData->m_nWidth = nWidth;
197 pRefData->m_nHeight = nHeight;
198 pRefData->m_nDepth = nDepth;
199 pRefData->m_nNumColors = 0;
200 pRefData->m_pSelectedInto = NULL;
3b9e3455 201
c354beea 202 hDc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
43543d98 203 hPs = ::GpiCreatePS(vHabmain, hDc, &vSize, GPIA_ASSOC | PU_PELS);
4f72fe4f 204 if (hPs == 0)
3b9e3455 205 {
2173b18f 206 wxLogLastError(wxT("GpiCreatePS Failure"));
3b9e3455 207 }
0e320a79 208
3437f881
DW
209 if (nDepth == 1)
210 {
211 //
212 // We assume that it is in XBM format which is not quite the same as
213 // the format CreateBitmap() wants because the order of bytes in the
d6922577 214 // line is reversed!
3437f881
DW
215 //
216 const size_t nBytesPerLine = (nWidth + 7) / 8;
217 const size_t nPadding = nBytesPerLine % 2;
218 const size_t nLen = nHeight * (nPadding + nBytesPerLine);
219 const char* pzSrc = zBits;
220 int nRows;
221 size_t nCols;
222
223 pzData = (char *)malloc(nLen);
224
225 char* pzDst = pzData;
226
227 for (nRows = 0; nRows < nHeight; nRows++)
228 {
229 for (nCols = 0; nCols < nBytesPerLine; nCols++)
230 {
6670f564
WS
231 unsigned char ucVal = *pzSrc++;
232 unsigned char ucReversed = 0;
233 int nBits;
0e320a79 234
3437f881
DW
235 for (nBits = 0; nBits < 8; nBits++)
236 {
237 ucReversed <<= 1;
6670f564 238 ucReversed = (unsigned char)(ucReversed | (ucVal & 0x01));
3437f881
DW
239 ucVal >>= 1;
240 }
241 *pzDst++ = ucReversed;
242 }
243 if (nPadding)
244 *pzDst++ = 0;
245 }
246 }
247 else
248 {
249 //
250 // Bits should already be in Windows standard format
251 //
252 pzData = (char *)zBits; // const_cast is harmless
253 }
254
ba3e10c9
DW
255 if (nDepth > 24)
256 nDepth = 24; // MAX supported in PM
c354beea
DW
257 memset(&vHeader, '\0', 16);
258 vHeader.cbFix = 16;
3437f881
DW
259 vHeader.cx = (USHORT)nWidth;
260 vHeader.cy = (USHORT)nHeight;
261 vHeader.cPlanes = 1L;
6670f564 262 vHeader.cBitCount = (USHORT)nDepth;
3437f881 263 vHeader.usReserved = 0;
c354beea
DW
264
265 memset(&vInfo, '\0', 16);
266 vInfo.cbFix = 16;
3437f881
DW
267 vInfo.cx = (USHORT)nWidth;
268 vInfo.cy = (USHORT)nHeight;
269 vInfo.cPlanes = 1L;
6670f564 270 vInfo.cBitCount = (USHORT)nDepth;
3437f881
DW
271
272 HBITMAP hBmp = ::GpiCreateBitmap(hPs, &vHeader, CBM_INIT, (PBYTE)pzData, &vInfo);
0e320a79 273
43543d98 274 if (!hBmp)
3b9e3455 275 {
2173b18f 276 wxLogLastError(wxT("CreateBitmap"));
3b9e3455 277 }
c354beea
DW
278 ::GpiDestroyPS(hPs);
279 ::DevCloseDC(hDc);
43543d98 280 SetHBITMAP((WXHBITMAP)hBmp);
6f38c86f 281} // end of wxBitmap::wxBitmap
0e320a79 282
3b9e3455
DW
283wxBitmap::wxBitmap(
284 int nW
285, int nH
286, int nD
287)
288{
289 Init();
3b9e3455
DW
290 (void)Create( nW
291 ,nH
292 ,nD
293 );
6f38c86f 294} // end of wxBitmap::wxBitmap
3b9e3455
DW
295
296wxBitmap::wxBitmap(
452418c4 297 const void* pData
3b9e3455
DW
298, long lType
299, int nWidth
300, int nHeight
301, int nDepth
302)
303{
304 Init();
305
306 (void)Create( pData
307 ,lType
308 ,nWidth
309 ,nHeight
310 ,nDepth
311 );
6f38c86f 312} // end of wxBitmap::wxBitmap
3b9e3455
DW
313
314wxBitmap::wxBitmap(
3029781e 315 int nId
3b9e3455
DW
316, long lType
317)
318{
319 Init();
3029781e 320 LoadFile( nId
3b9e3455
DW
321 ,(int)lType
322 );
70a2c656 323 SetId(nId);
6f38c86f 324} // end of wxBitmap::wxBitmap
3b9e3455
DW
325
326bool wxBitmap::Create(
327 int nW
328, int nH
329, int nD
330)
331{
332 HBITMAP hBmp;
333 BITMAPINFOHEADER2 vHeader;
3b9e3455 334
43543d98 335 wxASSERT(vHabmain != NULL);
0e320a79 336 UnRef();
0e320a79 337 m_refData = new wxBitmapRefData;
43543d98
DW
338 GetBitmapData()->m_nWidth = nW;
339 GetBitmapData()->m_nHeight = nH;
340 GetBitmapData()->m_nDepth = nD;
0e320a79 341
16ff355b
DW
342 //
343 // Xpms and bitmaps from other images can also be mono's, but only
344 // mono's need help changing their colors with MemDC changes
345 //
3b9e3455
DW
346 if (nD > 0)
347 {
6f38c86f
DW
348 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
349 SIZEL vSize = {0, 0};
350 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
351 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
352
ad6bd870 353 if (nD == 1)
d0ee33f5 354 m_bIsMono = true;
c354beea
DW
355 memset(&vHeader, '\0', 16);
356 vHeader.cbFix = 16;
6f38c86f
DW
357 vHeader.cx = nW;
358 vHeader.cy = nH;
359 vHeader.cPlanes = 1;
16ff355b 360 vHeader.cBitCount = 24; //nD;
6f38c86f
DW
361
362 hBmp = ::GpiCreateBitmap( hPS
363 ,&vHeader
364 ,0L
365 ,NULL
366 ,NULL
367 );
368 ::GpiDestroyPS(hPS);
369 ::DevCloseDC(hDC);
3b9e3455
DW
370 }
371 else
372 {
6f38c86f
DW
373 HPS hPSScreen;
374 HDC hDCScreen;
375 LONG lBitCount;
376
377 hPSScreen = ::WinGetScreenPS(HWND_DESKTOP);
378 hDCScreen = ::GpiQueryDevice(hPSScreen);
379 ::DevQueryCaps(hDCScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitCount);
380
ba3e10c9
DW
381 if (lBitCount > 24)
382 lBitCount = 24;
383
c354beea
DW
384 memset(&vHeader, '\0', 16);
385 vHeader.cbFix = 16;
6f38c86f
DW
386 vHeader.cx = nW;
387 vHeader.cy = nH;
388 vHeader.cPlanes = 1;
6670f564 389 vHeader.cBitCount = (USHORT)lBitCount;
6f38c86f
DW
390
391 hBmp = ::GpiCreateBitmap( hPSScreen
392 ,&vHeader
393 ,0L
394 ,NULL
395 ,NULL
396 );
4f72fe4f 397
43543d98 398 GetBitmapData()->m_nDepth = wxDisplayDepth();
6f38c86f 399 ::WinReleasePS(hPSScreen);
3b9e3455 400 }
4f72fe4f 401 SetHBITMAP((WXHBITMAP)hBmp);
0e320a79 402
3b9e3455 403 return Ok();
6f38c86f 404} // end of wxBitmap::Create
0e320a79 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 462bool wxBitmap::Create(
452418c4 463 const void* pData
4f72fe4f
DW
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 1221
cd7ff808
SN
1222wxMask::wxMask(const wxMask& tocopy)
1223{
a4e15a8d 1224 m_hMaskBitmap = wxCopyBmp(tocopy.m_hMaskBitmap);
cd7ff808
SN
1225} // end of wxMask::wxMask
1226
0e320a79
DW
1227// Construct a mask from a bitmap and a colour indicating
1228// the transparent area
4f72fe4f
DW
1229wxMask::wxMask(
1230 const wxBitmap& rBitmap
1231, const wxColour& rColour
1232)
0e320a79 1233{
4f72fe4f
DW
1234 m_hMaskBitmap = 0;
1235 Create( rBitmap
1236 ,rColour
1237 );
6f38c86f 1238} // end of wxMask::wxMask
0e320a79
DW
1239
1240// Construct a mask from a bitmap and a palette index indicating
1241// the transparent area
4f72fe4f
DW
1242wxMask::wxMask(
1243 const wxBitmap& rBitmap
1244, int nPaletteIndex
1245)
0e320a79 1246{
4f72fe4f
DW
1247 m_hMaskBitmap = 0;
1248 Create( rBitmap
1249 ,nPaletteIndex
1250 );
6f38c86f 1251} // end of wxMask::wxMask
0e320a79
DW
1252
1253// Construct a mask from a mono bitmap (copies the bitmap).
4f72fe4f
DW
1254wxMask::wxMask(
1255 const wxBitmap& rBitmap
1256)
0e320a79 1257{
4f72fe4f
DW
1258 m_hMaskBitmap = 0;
1259 Create(rBitmap);
6f38c86f 1260} // end of wxMask::wxMask
0e320a79
DW
1261
1262wxMask::~wxMask()
1263{
4f72fe4f
DW
1264 if (m_hMaskBitmap)
1265 ::GpiDeleteBitmap((HBITMAP)m_hMaskBitmap);
6f38c86f 1266} // end of wxMask::~wxMask
0e320a79
DW
1267
1268// Create a mask from a mono bitmap (copies the bitmap).
58b16424
DW
1269bool wxMask::Create(
1270 const wxBitmap& rBitmap
1271)
0e320a79 1272{
6f38c86f 1273 BITMAPINFOHEADER2 vBmih;
58b16424 1274 SIZEL vSize = {0, 0};
6f38c86f
DW
1275 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1276 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1277 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1278 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1279 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
3c623cf7
SN
1280 POINTL vPoint[4] = { {0 ,0}, {rBitmap.GetWidth(), rBitmap.GetHeight()},
1281 {0, 0}, {rBitmap.GetWidth(), rBitmap.GetHeight()}
6f38c86f 1282 };
58b16424
DW
1283
1284 if (m_hMaskBitmap)
3b9e3455 1285 {
58b16424
DW
1286 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1287 m_hMaskBitmap = 0;
3b9e3455 1288 }
58b16424 1289 if (!rBitmap.Ok() || rBitmap.GetDepth() != 1)
3b9e3455 1290 {
d0ee33f5 1291 return false;
3b9e3455 1292 }
6f38c86f
DW
1293
1294 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1295 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1296 vBmih.cx = rBitmap.GetWidth();
1297 vBmih.cy = rBitmap.GetHeight();
1298 vBmih.cPlanes = 1;
1c9a789e 1299 vBmih.cBitCount = 24;
6f38c86f
DW
1300
1301 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
1302 ,&vBmih
1303 ,0L
1304 ,NULL
1305 ,NULL
1306 );
1307
1308 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
1309 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
1310 ::GpiBitBlt( hPSDst
1311 ,hPSSrc
1312 ,4L
1313 ,vPoint
1314 ,ROP_SRCCOPY
1315 ,BBO_IGNORE
1316 );
1317
1318 ::GpiDestroyPS(hPSSrc);
1319 ::GpiDestroyPS(hPSDst);
1320 ::DevCloseDC(hDCSrc);
1321 ::DevCloseDC(hDCDst);
d0ee33f5 1322 return true;
6f38c86f 1323} // end of wxMask::Create
0e320a79
DW
1324
1325// Create a mask from a bitmap and a palette index indicating
1326// the transparent area
58b16424
DW
1327bool wxMask::Create(
1328 const wxBitmap& rBitmap
1329, int nPaletteIndex
1330)
0e320a79 1331{
58b16424 1332 if (m_hMaskBitmap)
3b9e3455 1333 {
58b16424
DW
1334 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1335 m_hMaskBitmap = 0;
3b9e3455 1336 }
58b16424 1337 if (rBitmap.Ok() && rBitmap.GetPalette()->Ok())
3b9e3455 1338 {
43543d98
DW
1339 unsigned char cRed;
1340 unsigned char cGreen;
1341 unsigned char cBlue;
1342
58b16424 1343 if (rBitmap.GetPalette()->GetRGB( nPaletteIndex
43543d98
DW
1344 ,&cRed
1345 ,&cGreen
1346 ,&cBlue
58b16424 1347 ))
3b9e3455 1348 {
43543d98
DW
1349 wxColour vTransparentColour( cRed
1350 ,cGreen
1351 ,cBlue
58b16424
DW
1352 );
1353
1354 return (Create( rBitmap
1355 ,vTransparentColour
1356 ));
3b9e3455
DW
1357 }
1358 }
d0ee33f5 1359 return false;
6f38c86f 1360} // end of wxMask::Create
0e320a79
DW
1361
1362// Create a mask from a bitmap and a colour indicating
1363// the transparent area
58b16424
DW
1364bool wxMask::Create(
1365 const wxBitmap& rBitmap
1366, const wxColour& rColour
1367)
0e320a79 1368{
d0ee33f5 1369 bool bOk = true;
6f38c86f
DW
1370 COLORREF vMaskColour = OS2RGB( rColour.Red()
1371 ,rColour.Green()
1372 ,rColour.Blue()
1373 );
1374 BITMAPINFOHEADER2 vBmih;
58b16424 1375 SIZEL vSize = {0, 0};
6f38c86f
DW
1376 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1377 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1378 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1379 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1380 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
58b16424
DW
1381
1382 if (m_hMaskBitmap)
3b9e3455 1383 {
58b16424
DW
1384 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1385 m_hMaskBitmap = 0;
3b9e3455 1386 }
58b16424 1387 if (!rBitmap.Ok())
3b9e3455 1388 {
d0ee33f5 1389 return false;
3b9e3455
DW
1390 }
1391
6f38c86f
DW
1392 //
1393 // Scan the bitmap for the transparent colour and set
3b9e3455
DW
1394 // the corresponding pixels in the mask to BLACK and
1395 // the rest to WHITE
6f38c86f
DW
1396 //
1397
1398 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1399 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1400 vBmih.cx = rBitmap.GetWidth();
1401 vBmih.cy = rBitmap.GetHeight();
1402 vBmih.cPlanes = 1;
1403 vBmih.cBitCount = 1;
1404
1405 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
1406 ,&vBmih
1407 ,0L
1408 ,NULL
1409 ,NULL
1410 );
1411
1412 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
1413 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
1414
1415 //
1416 // This is not very efficient, but I can't think
3b9e3455 1417 // of a better way of doing it
6f38c86f 1418 //
58b16424 1419 for (int w = 0; w < rBitmap.GetWidth(); w++)
3b9e3455 1420 {
58b16424 1421 for (int h = 0; h < rBitmap.GetHeight(); h++)
3b9e3455 1422 {
6f38c86f
DW
1423 POINTL vPt = {w, h};
1424 COLORREF vCol = (COLORREF)::GpiQueryPel(hPSSrc, &vPt);
1425 if (vCol == (COLORREF)CLR_NOINDEX)
1426 {
1427 //
1428 // Doesn't make sense to continue
1429 //
d0ee33f5 1430 bOk = false;
6f38c86f
DW
1431 break;
1432 }
58b16424 1433
6f38c86f 1434 if (vCol == vMaskColour)
3b9e3455 1435 {
6f38c86f
DW
1436 ::GpiSetColor(hPSDst, OS2RGB(0, 0, 0));
1437 ::GpiSetPel(hPSDst, &vPt);
3b9e3455
DW
1438 }
1439 else
1440 {
6f38c86f
DW
1441 ::GpiSetColor(hPSDst, OS2RGB(255, 255, 255));
1442 ::GpiSetPel(hPSDst, &vPt);
3b9e3455
DW
1443 }
1444 }
1445 }
6f38c86f
DW
1446 ::GpiSetBitmap(hPSSrc, NULL);
1447 ::GpiSetBitmap(hPSDst, NULL);
1448 ::GpiDestroyPS(hPSSrc);
1449 ::GpiDestroyPS(hPSDst);
1450 ::DevCloseDC(hDCSrc);
1451 ::DevCloseDC(hDCDst);
d0ee33f5 1452 return true;
6f38c86f 1453} // end of wxMask::Create
0e320a79 1454
3b9e3455
DW
1455// ----------------------------------------------------------------------------
1456// wxBitmapHandler
1457// ----------------------------------------------------------------------------
0e320a79 1458
6670f564 1459bool wxBitmapHandler::Create( wxGDIImage* pImage,
452418c4 1460 const void* pData,
6670f564
WS
1461 long WXUNUSED(lFlags),
1462 int nWidth,
1463 int nHeight,
1464 int nDepth)
3b9e3455 1465{
6670f564
WS
1466 wxBitmap* pBitmap = wxDynamicCast( pImage
1467 ,wxBitmap
1468 );
3b9e3455 1469
58b16424
DW
1470 return(pBitmap ? Create( pBitmap
1471 ,pData
1472 ,nWidth
1473 ,nHeight
1474 ,nDepth
d0ee33f5 1475 ) : false);
3b9e3455
DW
1476}
1477
58b16424
DW
1478bool wxBitmapHandler::Load(
1479 wxGDIImage* pImage
3029781e 1480, int nId
58b16424
DW
1481, long lFlags
1482, int nWidth
1483, int nHeight
1484)
3b9e3455 1485{
43543d98
DW
1486 wxBitmap* pBitmap = wxDynamicCast( pImage
1487 ,wxBitmap
1488 );
3b9e3455 1489
58b16424 1490 return(pBitmap ? LoadFile( pBitmap
3029781e 1491 ,nId
58b16424
DW
1492 ,lFlags
1493 ,nWidth
1494 ,nHeight
d0ee33f5 1495 ) : false);
3b9e3455
DW
1496}
1497
58b16424
DW
1498bool wxBitmapHandler::Save(
1499 wxGDIImage* pImage
1500, const wxString& rName
1501, int lType
1502)
0e320a79 1503{
58b16424
DW
1504 wxBitmap* pBitmap = wxDynamicCast( pImage
1505 ,wxBitmap
1506 );
0e320a79 1507
58b16424
DW
1508 return(pBitmap ? SaveFile( pBitmap
1509 ,rName
1510 ,lType
d0ee33f5 1511 ) : false);
0e320a79
DW
1512}
1513
58b16424
DW
1514bool wxBitmapHandler::Create(
1515 wxBitmap* WXUNUSED(pBitmap)
452418c4 1516, const void* WXUNUSED(pData)
58b16424
DW
1517, long WXUNUSED(lType)
1518, int WXUNUSED(nWidth)
1519, int WXUNUSED(nHeight)
1520, int WXUNUSED(nDepth)
1521)
0e320a79 1522{
d0ee33f5 1523 return false;
0e320a79
DW
1524}
1525
58b16424
DW
1526bool wxBitmapHandler::LoadFile(
1527 wxBitmap* WXUNUSED(pBitmap)
3029781e 1528, int WXUNUSED(nId)
58b16424
DW
1529, long WXUNUSED(lType)
1530, int WXUNUSED(nDesiredWidth)
1531, int WXUNUSED(nDesiredHeight)
1532)
0e320a79 1533{
d0ee33f5 1534 return false;
0e320a79
DW
1535}
1536
c90c3400
SN
1537bool wxBitmapHandler::LoadFile(
1538 wxBitmap* WXUNUSED(pBitmap)
1539, const wxString& WXUNUSED(rName)
1540, long WXUNUSED(lType)
1541, int WXUNUSED(nDesiredWidth)
1542, int WXUNUSED(nDesiredHeight)
1543)
1544{
1545 return false;
1546}
1547
58b16424
DW
1548bool wxBitmapHandler::SaveFile(
1549 wxBitmap* WXUNUSED(pBitmap)
1550, const wxString& WXUNUSED(rName)
1551, int WXUNUSED(nType)
1552, const wxPalette* WXUNUSED(pPalette)
1553)
0e320a79 1554{
d0ee33f5 1555 return false;
0e320a79 1556}
ce44c50e 1557
020a1653
DW
1558// ----------------------------------------------------------------------------
1559// Utility functions
1560// ----------------------------------------------------------------------------
1561HBITMAP wxInvertMask(
1562 HBITMAP hBmpMask
1563, int nWidth
1564, int nHeight
1565)
1566{
1567 HBITMAP hBmpInvMask = 0;
1568
1569 wxCHECK_MSG( hBmpMask, 0, _T("invalid bitmap in wxInvertMask") );
1570
1571 //
1572 // Get width/height from the bitmap if not given
1573 //
1574 if (!nWidth || !nHeight)
1575 {
1576 BITMAPINFOHEADER2 vBmhdr;
1577
1578 ::GpiQueryBitmapInfoHeader( hBmpMask
1579 ,&vBmhdr
1580 );
1581 nWidth = (int)vBmhdr.cx;
e464c180 1582 nHeight = (int)vBmhdr.cy;
020a1653
DW
1583 }
1584
1585 BITMAPINFOHEADER2 vBmih;
1586 SIZEL vSize = {0, 0};
1587 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
e464c180
DW
1588 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1589 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1590 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1591 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
3c623cf7
SN
1592 POINTL vPoint[4] = { {0 ,0}, {nWidth, nHeight},
1593 {0, 0}, {nWidth, nHeight}
020a1653
DW
1594 };
1595
1c9a789e
DW
1596 memset(&vBmih, '\0', 16);
1597 vBmih.cbFix = 16;
e464c180
DW
1598 vBmih.cx = nWidth;
1599 vBmih.cy = nHeight;
020a1653 1600 vBmih.cPlanes = 1;
1c9a789e 1601 vBmih.cBitCount = 24;
020a1653
DW
1602
1603 hBmpInvMask = ::GpiCreateBitmap( hPSDst
1604 ,&vBmih
1605 ,0L
1606 ,NULL
1607 ,NULL
1608 );
1609
1610 ::GpiSetBitmap(hPSSrc, (HBITMAP) hBmpMask);
1611 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpInvMask);
1612
1613 ::GpiBitBlt( hPSDst
1614 ,hPSSrc
1615 ,4L
e464c180 1616 ,vPoint
8e8d8eef 1617 ,ROP_SRCINVERT
020a1653
DW
1618 ,BBO_IGNORE
1619 );
1620
1621 ::GpiDestroyPS(hPSSrc);
1622 ::GpiDestroyPS(hPSDst);
1623 ::DevCloseDC(hDCSrc);
e464c180 1624 ::DevCloseDC(hDCDst);
020a1653
DW
1625
1626 return hBmpInvMask;
1627} // end of WxWinGdi_InvertMask
59fb774d 1628
a4e15a8d 1629HBITMAP wxCopyBmp( HBITMAP hBmp, bool flip, int nWidth, int nHeight )
59fb774d 1630{
a4e15a8d 1631 wxCHECK_MSG( hBmp, 0, _T("invalid bitmap in wxCopyBmp") );
59fb774d
SN
1632
1633 //
1634 // Get width/height from the bitmap if not given
1635 //
1636 if (!nWidth || !nHeight)
1637 {
1638 BITMAPINFOHEADER2 vBmhdr;
1639
1640 vBmhdr.cbFix = 16;
1641 ::GpiQueryBitmapInfoHeader( hBmp,
1642 &vBmhdr );
1643 nWidth = (int)vBmhdr.cx;
1644 nHeight = (int)vBmhdr.cy;
1645 }
1646
1647 BITMAPINFOHEADER2 vBmih;
1648 SIZEL vSize = {0, 0};
1649 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1650 HDC hDCSrc = ::DevOpenDC( vHabmain,
1651 OD_MEMORY,
1652 "*",
1653 5L,
1654 (PDEVOPENDATA)&vDop,
1655 NULLHANDLE );
1656 HDC hDCDst = ::DevOpenDC( vHabmain,
1657 OD_MEMORY,
1658 "*",
1659 5L,
1660 (PDEVOPENDATA)&vDop,
1661 NULLHANDLE );
1662 HPS hPSSrc = ::GpiCreatePS( vHabmain,
1663 hDCSrc,
1664 &vSize,
1665 PU_PELS | GPIA_ASSOC );
1666 HPS hPSDst = ::GpiCreatePS( vHabmain,
1667 hDCDst,
1668 &vSize,
1669 PU_PELS | GPIA_ASSOC );
1670 POINTL vPoint[4] = { {0, nHeight},
1671 {nWidth, 0},
1672 {0, 0},
1673 {nWidth, nHeight} };
a4e15a8d
SN
1674 if (!flip)
1675 {
1676 vPoint[0].y = 0;
1677 vPoint[1].y = nHeight;
1678 }
59fb774d
SN
1679 memset(&vBmih, '\0', 16);
1680 vBmih.cbFix = 16;
1681 vBmih.cx = nWidth;
1682 vBmih.cy = nHeight;
1683 vBmih.cPlanes = 1;
1684 vBmih.cBitCount = 24;
1685
1686 HBITMAP hInvBmp = ::GpiCreateBitmap( hPSDst,
1687 &vBmih,
1688 0L,
1689 NULL,
1690 NULL );
1691
1692 ::GpiSetBitmap(hPSSrc, (HBITMAP) hBmp);
1693 ::GpiSetBitmap(hPSDst, (HBITMAP) hInvBmp);
1694
1695 ::GpiBitBlt( hPSDst,
1696 hPSSrc,
1697 4L,
1698 vPoint,
1699 ROP_SRCCOPY,
1700 BBO_IGNORE );
1701
1702 ::GpiDestroyPS(hPSSrc);
1703 ::GpiDestroyPS(hPSDst);
1704 ::DevCloseDC(hDCSrc);
1705 ::DevCloseDC(hDCDst);
1706
1707 return hInvBmp;
1708} // end of wxFlipBmp