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