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