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