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