]> git.saurik.com Git - wxWidgets.git/blame - src/os2/bitmap.cpp
wxBase/GUI separation: 1st step, wxMSW should build, all the rest is broken
[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;
70a2c656 61 m_hBitmap = (WXHBITMAP) NULL;
341366c6 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 }
2590f154
DW
77 if (m_pBitmapMask)
78 {
79 delete m_pBitmapMask;
80 m_pBitmapMask = NULL;
81 }
341366c6 82} // end of wxBitmapRefData::Free
0e320a79 83
3b9e3455
DW
84// ----------------------------------------------------------------------------
85// wxBitmap creation
86// ----------------------------------------------------------------------------
0e320a79 87
3b9e3455
DW
88// this function should be called from all wxBitmap ctors
89void wxBitmap::Init()
0e320a79 90{
16ff355b 91 m_bIsMono = FALSE;
1c9a789e
DW
92 //
93 // True for all bitmaps created from bits, wxImages, Xpms
94 //
6f38c86f 95} // end of wxBitmap::Init
0e320a79 96
3b9e3455
DW
97bool wxBitmap::CopyFromIconOrCursor(
98 const wxGDIImage& rIcon
99)
d88de032 100{
6f38c86f
DW
101 HPOINTER hIcon = (HPOINTER)rIcon.GetHandle();
102 POINTERINFO SIconInfo;
103
104 if (!::WinQueryPointerInfo(hIcon, &SIconInfo))
105 {
106 wxLogLastError(wxT("WinQueryPointerInfo"));
107 return FALSE;
108 }
3b9e3455 109 wxBitmapRefData* pRefData = new wxBitmapRefData;
d88de032 110
3b9e3455 111 m_refData = pRefData;
d88de032 112
6f38c86f
DW
113 int nWidth = rIcon.GetWidth();
114 int nHeight = rIcon.GetHeight();
d88de032 115
6f38c86f
DW
116 pRefData->m_nWidth = nWidth;
117 pRefData->m_nHeight = nHeight;
118 pRefData->m_nDepth = wxDisplayDepth();
d88de032 119
6f38c86f
DW
120 pRefData->m_hBitmap = (WXHBITMAP)SIconInfo.hbmColor;
121
16ff355b
DW
122 wxMask* pMask = new wxMask(SIconInfo.hbmPointer);
123
124 pMask->SetMaskBitmap(GetHBITMAP());
125 SetMask(pMask);
126
3b9e3455 127 return(TRUE);
6f38c86f 128} // end of wxBitmap::CopyFromIconOrCursor
0e320a79 129
3b9e3455
DW
130bool wxBitmap::CopyFromCursor(
131 const wxCursor& rCursor
132)
d88de032 133{
3b9e3455 134 UnRef();
d88de032 135
3b9e3455
DW
136 if (!rCursor.Ok())
137 return(FALSE);
43543d98 138 return(CopyFromIconOrCursor(rCursor));
6f38c86f 139} // end of wxBitmap::CopyFromCursor
d88de032 140
3b9e3455
DW
141bool wxBitmap::CopyFromIcon(
142 const wxIcon& rIcon
143)
0e320a79 144{
3b9e3455 145 UnRef();
0e320a79 146
3b9e3455
DW
147 if (!rIcon.Ok())
148 return(FALSE);
0e320a79 149
43543d98 150 return CopyFromIconOrCursor(rIcon);
6f38c86f 151} // end of wxBitmap::CopyFromIcon
0e320a79 152
3b9e3455 153wxBitmap::~wxBitmap()
d88de032 154{
6f38c86f 155} // end of wxBitmap::~wxBitmap
d88de032 156
3b9e3455
DW
157wxBitmap::wxBitmap(
158 const char zBits[]
3437f881
DW
159, int nWidth
160, int nHeight
161, int nDepth
3b9e3455
DW
162)
163{
164 Init();
165
166 wxBitmapRefData* pRefData = new wxBitmapRefData;
167 BITMAPINFOHEADER2 vHeader;
168 BITMAPINFO2 vInfo;
169 HDC hDc;
170 HPS hPs;
43543d98 171 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
3b9e3455 172 SIZEL vSize = {0, 0};
3437f881 173 char* pzData;
3b9e3455 174
43543d98 175 wxASSERT(vHabmain != NULL);
3b9e3455 176
3437f881 177 m_refData = pRefData;
3b9e3455 178
3437f881
DW
179 pRefData->m_nWidth = nWidth;
180 pRefData->m_nHeight = nHeight;
181 pRefData->m_nDepth = nDepth;
182 pRefData->m_nNumColors = 0;
183 pRefData->m_pSelectedInto = NULL;
3b9e3455 184
c354beea 185 hDc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
43543d98 186 hPs = ::GpiCreatePS(vHabmain, hDc, &vSize, GPIA_ASSOC | PU_PELS);
4f72fe4f 187 if (hPs == 0)
3b9e3455
DW
188 {
189 wxLogLastError("GpiCreatePS Failure");
190 }
0e320a79 191
3437f881
DW
192 if (nDepth == 1)
193 {
194 //
195 // We assume that it is in XBM format which is not quite the same as
196 // the format CreateBitmap() wants because the order of bytes in the
197 // line is inversed!
198 //
199 const size_t nBytesPerLine = (nWidth + 7) / 8;
200 const size_t nPadding = nBytesPerLine % 2;
201 const size_t nLen = nHeight * (nPadding + nBytesPerLine);
202 const char* pzSrc = zBits;
203 int nRows;
204 size_t nCols;
205
206 pzData = (char *)malloc(nLen);
207
208 char* pzDst = pzData;
209
210 for (nRows = 0; nRows < nHeight; nRows++)
211 {
212 for (nCols = 0; nCols < nBytesPerLine; nCols++)
213 {
214 unsigned char ucVal = *pzSrc++;
215 unsigned char ucReversed = 0;
216 int nBits;
0e320a79 217
3437f881
DW
218 for (nBits = 0; nBits < 8; nBits++)
219 {
220 ucReversed <<= 1;
221 ucReversed |= (ucVal & 0x01);
222 ucVal >>= 1;
223 }
224 *pzDst++ = ucReversed;
225 }
226 if (nPadding)
227 *pzDst++ = 0;
228 }
229 }
230 else
231 {
232 //
233 // Bits should already be in Windows standard format
234 //
235 pzData = (char *)zBits; // const_cast is harmless
236 }
237
ba3e10c9
DW
238 if (nDepth > 24)
239 nDepth = 24; // MAX supported in PM
c354beea
DW
240 memset(&vHeader, '\0', 16);
241 vHeader.cbFix = 16;
3437f881
DW
242 vHeader.cx = (USHORT)nWidth;
243 vHeader.cy = (USHORT)nHeight;
244 vHeader.cPlanes = 1L;
245 vHeader.cBitCount = nDepth;
246 vHeader.usReserved = 0;
c354beea
DW
247
248 memset(&vInfo, '\0', 16);
249 vInfo.cbFix = 16;
3437f881
DW
250 vInfo.cx = (USHORT)nWidth;
251 vInfo.cy = (USHORT)nHeight;
252 vInfo.cPlanes = 1L;
253 vInfo.cBitCount = nDepth;
3437f881
DW
254
255 HBITMAP hBmp = ::GpiCreateBitmap(hPs, &vHeader, CBM_INIT, (PBYTE)pzData, &vInfo);
0e320a79 256
43543d98 257 if (!hBmp)
3b9e3455
DW
258 {
259 wxLogLastError("CreateBitmap");
260 }
c354beea
DW
261 ::GpiDestroyPS(hPs);
262 ::DevCloseDC(hDc);
43543d98 263 SetHBITMAP((WXHBITMAP)hBmp);
6f38c86f 264} // end of wxBitmap::wxBitmap
0e320a79 265
3b9e3455
DW
266wxBitmap::wxBitmap(
267 int nW
268, int nH
269, int nD
270)
271{
272 Init();
3b9e3455
DW
273 (void)Create( nW
274 ,nH
275 ,nD
276 );
6f38c86f 277} // end of wxBitmap::wxBitmap
3b9e3455
DW
278
279wxBitmap::wxBitmap(
280 void* pData
281, long lType
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
3b9e3455
DW
299, long lType
300)
301{
302 Init();
3029781e 303 LoadFile( nId
3b9e3455
DW
304 ,(int)lType
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
DW
336 if (nD == 1)
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;
372 vHeader.cBitCount = lBitCount;
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#if WXWIN_COMPATIBILITY_2
4f72fe4f 387 GetBitmapData()->m_bOk = hBmp != 0;
3b9e3455
DW
388#endif // WXWIN_COMPATIBILITY_2
389
390 return Ok();
6f38c86f 391} // end of wxBitmap::Create
0e320a79 392
1c344e89
DW
393bool wxBitmap::CreateFromXpm(
394 const char** ppData
395)
396{
397#if wxUSE_IMAGE && wxUSE_XPM
398 Init();
399
400 wxCHECK_MSG(ppData != NULL, FALSE, wxT("invalid bitmap data"))
401
402 wxXPMDecoder vDecoder;
403 wxImage vImg = vDecoder.ReadData(ppData);
404
405 wxCHECK_MSG(vImg.Ok(), FALSE, wxT("invalid bitmap data"))
406
407 *this = wxBitmap(vImg);
408 return TRUE;
409#else
410 return FALSE;
411#endif
412} // end of wxBitmap::CreateFromXpm
413
4f72fe4f 414bool wxBitmap::LoadFile(
3029781e 415 int nId
4f72fe4f
DW
416, long lType
417)
0e320a79 418{
4e0f4f97 419 HPS hPs = NULLHANDLE;
8ea3f821 420
0e320a79
DW
421 UnRef();
422
4f72fe4f
DW
423 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
424 ,wxBitmapHandler
425 );
0e320a79 426
4f72fe4f 427 if (pHandler)
3b9e3455
DW
428 {
429 m_refData = new wxBitmapRefData;
0e320a79 430
4f72fe4f 431 return(pHandler->LoadFile( this
3029781e 432 ,nId
4f72fe4f
DW
433 ,lType
434 , -1
435 , -1
43543d98 436 ));
0e320a79 437 }
3b9e3455
DW
438 else
439 {
3029781e 440 return(FALSE);
3b9e3455 441 }
6f38c86f 442} // end of wxBitmap::LoadFile
0e320a79 443
4f72fe4f
DW
444bool wxBitmap::Create(
445 void* pData
446, long lType
447, int nWidth
448, int nHeight
449, int nDepth
450)
0e320a79
DW
451{
452 UnRef();
453
4f72fe4f
DW
454 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
455 ,wxBitmapHandler
456 );
0e320a79 457
4f72fe4f 458 if (!pHandler)
3b9e3455
DW
459 {
460 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
43543d98 461 "type %d defined."), lType);
0e320a79 462
4f72fe4f 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
DW
478 const wxString& rFilename
479, int lType
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())
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{
3437f881 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 //
556 wxCHECK_MSG(rImage.Ok(), FALSE, wxT("invalid image"));
557 SetWidth(nWidth);
558 SetHeight(nBmpHeight);
ad6bd870
DW
559 if (nDepth == 1)
560 m_bIsMono = TRUE;
561 else
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"));
599 return FALSE;
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
3437f881
DW
705 POINTL vPoint[4] = { 0, nOrigin,
706 nWidth, nHeight,
707 0, 0, nWidth, nHeight
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 );
806 POINTL vPoint2[4] = { 0, nOrigin,
807 nWidth, nHeight,
808 0, 0, nWidth, nHeight
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);
fec19ea9 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
DW
865 HPS hPSMem;
866 HPS hPS;
3437f881 867 HBITMAP hBitmap;
1cee3f60
DW
868 HBITMAP hOldBitmap;
869 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
870 SIZEL vSizlPage = {0,0};
871 HDC hDCMem;
3437f881
DW
872
873 vImage.Create( nWidth
874 ,nHeight
875 );
876 pData = vImage.GetData();
877 if(!pData)
fec19ea9
VS
878 {
879 wxFAIL_MSG( wxT("could not allocate data for image") );
880 return wxNullImage;
881 }
3437f881 882 if(nLineBoundary > 0)
fec19ea9 883 {
3437f881
DW
884 nPadding = nSizeDWORD - nLineBoundary;
885 nBytePerLine += nPadding;
fec19ea9 886 }
3437f881
DW
887 wxDisplaySize( &nDevWidth
888 ,&nDevHeight
889 );
890 //
891 // Create and fill a DIB header
892 //
c354beea
DW
893 memset(&vDIBh, '\0', 16);
894 vDIBh.cbFix = 16;
3437f881
DW
895 vDIBh.cx = nWidth;
896 vDIBh.cy = nHeight;
897 vDIBh.cPlanes = 1;
3437f881
DW
898 vDIBh.cBitCount = 24;
899
c354beea
DW
900 memset(&vDIBInfo, '\0', 16);
901 vDIBInfo.cbFix = 16;
902 vDIBInfo.cx = nWidth;
903 vDIBInfo.cy = nHeight;
3437f881 904 vDIBInfo.cPlanes = 1;
52315bc3 905 vDIBInfo.cBitCount = 24;
c354beea
DW
906
907 lpBits = (unsigned char *)malloc(nBytePerLine * nHeight);
3437f881 908 if (!lpBits)
fec19ea9 909 {
3437f881
DW
910 wxFAIL_MSG(wxT("could not allocate data for DIB"));
911 free(pData);
912 return wxNullImage;
fec19ea9 913 }
52315bc3
DW
914 memset(lpBits, '\0', (nBytePerLine * nHeight));
915 hBitmap = (HBITMAP)GetHBITMAP();
fec19ea9 916
1cee3f60
DW
917 //
918 // May already be selected into a PS
919 //
920 if ((pDC = GetSelectedInto()) != NULL)
921 {
922 hPSMem = pDC->GetHPS();
923 }
924 else
925 {
926 hDCMem = ::DevOpenDC( vHabmain
927 ,OD_MEMORY
928 ,"*"
929 ,5L
930 ,(PDEVOPENDATA)&vDop
931 ,NULLHANDLE
932 );
933 hPSMem = ::GpiCreatePS( vHabmain
934 ,hDCMem
935 ,&vSizlPage
936 ,PU_PELS | GPIA_ASSOC
937 );
29172908
DW
938 }
939 if ((hOldBitmap = ::GpiSetBitmap(hPSMem, hBitmap)) == HBM_ERROR)
940 {
941 ERRORID vError;
942 wxString sError;
1cee3f60 943
29172908
DW
944 vError = ::WinGetLastError(vHabmain);
945 sError = wxPMErrorToStr(vError);
1cee3f60
DW
946 }
947
3437f881
DW
948 //
949 // Copy data from the device-dependent bitmap to the DIB
950 //
1cee3f60
DW
951 if ((lScans = ::GpiQueryBitmapBits( hPSMem
952 ,0L
953 ,(LONG)nHeight
954 ,(PBYTE)lpBits
955 ,&vDIBInfo
956 )) == GPI_ALTERROR)
957 {
958 ERRORID vError;
959 wxString sError;
960
961 vError = ::WinGetLastError(vHabmain);
962 sError = wxPMErrorToStr(vError);
963 }
3437f881
DW
964
965 //
966 // Copy DIB data into the wxImage object
967 //
968 int i;
969 int j;
970 unsigned char* ptdata = pData;
971 unsigned char* ptbits = lpBits;
972
973 for (i = 0; i < nHeight; i++)
fec19ea9 974 {
3437f881 975 for (j = 0; j < nWidth; j++)
fec19ea9
VS
976 {
977 *(ptdata++) = *(ptbits+2);
978 *(ptdata++) = *(ptbits+1);
979 *(ptdata++) = *(ptbits );
980 ptbits += 3;
981 }
3437f881 982 ptbits += nPadding;
fec19ea9 983 }
1cee3f60
DW
984 if ((pDC = GetSelectedInto()) == NULL)
985 {
986 ::GpiSetBitmap(hPSMem, NULLHANDLE);
987 ::GpiDestroyPS(hPSMem);
988 ::DevCloseDC(hDCMem);
989 }
fec19ea9 990
3437f881
DW
991 //
992 // Similarly, set data according to the possible mask bitmap
993 //
994 if (GetMask() && GetMask()->GetMaskBitmap())
fec19ea9 995 {
3437f881
DW
996 hBitmap = (HBITMAP)GetMask()->GetMaskBitmap();
997
998 //
999 // Memory DC/PS created, color set, data copied, and memory DC/PS deleted
1000 //
1cee3f60
DW
1001 HDC hMemDC = ::DevOpenDC( vHabmain
1002 ,OD_MEMORY
1003 ,"*"
1004 ,5L
1005 ,(PDEVOPENDATA)&vDop
1006 ,NULLHANDLE
1007 );
3437f881
DW
1008 HPS hMemPS = ::GpiCreatePS( vHabmain
1009 ,hMemDC
1010 ,&vSizlPage
b1b054da 1011 ,PU_PELS | GPIA_ASSOC
3437f881
DW
1012 );
1013 ::GpiSetColor(hMemPS, OS2RGB(0, 0, 0));
1014 ::GpiSetBackColor(hMemPS, OS2RGB(255, 255, 255) );
1d0edc0f 1015 ::GpiSetBitmap(hMemPS, hBitmap);
3437f881
DW
1016 ::GpiQueryBitmapBits( hPSMem
1017 ,0L
1018 ,(LONG)nHeight
1019 ,(PBYTE)lpBits
1020 ,&vDIBInfo
1021 );
1d0edc0f 1022 ::GpiSetBitmap(hMemPS, NULLHANDLE);
3437f881
DW
1023 ::GpiDestroyPS(hMemPS);
1024 ::DevCloseDC(hMemDC);
1025
1026 //
1027 // Background color set to RGB(16,16,16) in consistent with wxGTK
1028 //
1029 unsigned char ucRed = 16;
1030 unsigned char ucGreen = 16;
1031 unsigned char ucBlue = 16;
1032
1033 ptdata = pData;
fec19ea9 1034 ptbits = lpBits;
3437f881 1035 for (i = 0; i < nHeight; i++)
fec19ea9 1036 {
3437f881 1037 for (j = 0; j < nWidth; j++)
fec19ea9 1038 {
3437f881 1039 if (*ptbits != 0)
fec19ea9
VS
1040 ptdata += 3;
1041 else
1042 {
3437f881
DW
1043 *(ptdata++) = ucRed;
1044 *(ptdata++) = ucGreen;
1045 *(ptdata++) = ucBlue;
fec19ea9
VS
1046 }
1047 ptbits += 3;
1048 }
3437f881 1049 ptbits += nPadding;
fec19ea9 1050 }
3437f881
DW
1051 vImage.SetMaskColour( ucRed
1052 ,ucGreen
1053 ,ucBlue
1054 );
1055 vImage.SetMask(TRUE);
fec19ea9
VS
1056 }
1057 else
1058 {
3437f881 1059 vImage.SetMask(FALSE);
fec19ea9 1060 }
fec19ea9 1061
3437f881
DW
1062 //
1063 // Free allocated resources
1064 //
3437f881
DW
1065 free(lpBits);
1066 return vImage;
1067} // end of wxBitmap::ConvertToImage
fec19ea9 1068
6f38c86f
DW
1069// ----------------------------------------------------------------------------
1070// sub bitmap extraction
1071// ----------------------------------------------------------------------------
1072
1073wxBitmap wxBitmap::GetSubBitmap(
1074 const wxRect& rRect
1075) const
1076{
1077 wxCHECK_MSG( Ok() &&
1078 (rRect.x >= 0) && (rRect.y >= 0) &&
1079 (rRect.x + rRect.width <= GetWidth()) &&
1080 (rRect.y + rRect.height <= GetHeight()),
1081 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
1082
1083 wxBitmap vRet( rRect.width
1084 ,rRect.height
1085 ,GetDepth()
1086 );
1087 wxASSERT_MSG( vRet.Ok(), wxT("GetSubBitmap error") );
1088
1089
1090 //
1091 // Copy bitmap data
1092 //
1093 SIZEL vSize = {0, 0};
1094 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1095 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1096 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1097 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1098 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
c354beea 1099 POINTL vPoint[4] = { 0, 0, rRect.width, rRect.height,
1d0edc0f 1100 rRect.x, rRect.y,
c354beea 1101 rRect.x + rRect.width, rRect.y + rRect.height
6f38c86f
DW
1102 };
1103
1104 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetHBITMAP());
1105 ::GpiSetBitmap(hPSDst, (HBITMAP) vRet.GetHBITMAP());
1106 ::GpiBitBlt( hPSDst
1107 ,hPSSrc
1108 ,4L
1109 ,vPoint
1110 ,ROP_SRCCOPY
1111 ,BBO_IGNORE
1112 );
1113
1114 //
1115 // Copy mask if there is one
1116 //
1117 if (GetMask())
1118 {
1119 BITMAPINFOHEADER2 vBmih;
1120
1121 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1122 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1123 vBmih.cx = rRect.width;
1124 vBmih.cy = rRect.height;
1125 vBmih.cPlanes = 1;
1c9a789e 1126 vBmih.cBitCount = 24;
6f38c86f
DW
1127
1128 HBITMAP hBmpMask = ::GpiCreateBitmap( hPSDst
1129 ,&vBmih
1130 ,0L
1131 ,NULL
1132 ,NULL
1133 );
1134
1135 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetHBITMAP());
1136 ::GpiSetBitmap(hPSDst, (HBITMAP) vRet.GetHBITMAP());
1137
1138 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetMask()->GetMaskBitmap());
1139 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpMask);
1140 ::GpiBitBlt( hPSDst
1141 ,hPSSrc
1142 ,4L
1143 ,vPoint
1144 ,ROP_SRCCOPY
1145 ,BBO_IGNORE
1146 );
1147
1148 wxMask* pMask = new wxMask((WXHBITMAP)hBmpMask);
1149 vRet.SetMask(pMask);
1150 }
1151
1152 ::GpiSetBitmap(hPSSrc, NULL);
1153 ::GpiSetBitmap(hPSDst, NULL);
1154 ::GpiDestroyPS(hPSSrc);
1155 ::GpiDestroyPS(hPSDst);
1156 ::DevCloseDC(hDCSrc);
1157 ::DevCloseDC(hDCDst);
1158 return vRet;
1159} // end of wxBitmap::GetSubBitmap
0e320a79 1160
3b9e3455
DW
1161// ----------------------------------------------------------------------------
1162// wxBitmap accessors
1163// ----------------------------------------------------------------------------
0e320a79 1164
4f72fe4f
DW
1165void wxBitmap::SetQuality(
1166 int nQ
1167)
0e320a79 1168{
3b9e3455 1169 EnsureHasData();
0e320a79 1170
4f72fe4f 1171 GetBitmapData()->m_nQuality = nQ;
6f38c86f 1172} // end of wxBitmap::SetQuality
0e320a79 1173
3b9e3455 1174#if WXWIN_COMPATIBILITY_2
4f72fe4f
DW
1175void wxBitmap::SetOk(
1176 bool bOk
1177)
0e320a79 1178{
3b9e3455 1179 EnsureHasData();
0e320a79 1180
4f72fe4f 1181 GetBitmapData()->m_bOk = bOk;
6f38c86f 1182} // end of wxBitmap::SetOk
3b9e3455 1183#endif // WXWIN_COMPATIBILITY_2
0e320a79 1184
4f72fe4f
DW
1185void wxBitmap::SetPalette(
1186 const wxPalette& rPalette
1187)
0e320a79 1188{
3b9e3455 1189 EnsureHasData();
0e320a79 1190
4f72fe4f 1191 GetBitmapData()->m_vBitmapPalette = rPalette;
6f38c86f 1192} // end of wxBitmap::SetPalette
0e320a79 1193
4f72fe4f
DW
1194void wxBitmap::SetMask(
1195 wxMask* pMask
1196)
0e320a79 1197{
3b9e3455 1198 EnsureHasData();
0e320a79 1199
4f72fe4f 1200 GetBitmapData()->m_pBitmapMask = pMask;
6f38c86f 1201} // end of wxBitmap::SetMask
0e320a79 1202
4f72fe4f
DW
1203wxBitmap wxBitmap::GetBitmapForDC(
1204 wxDC& rDc
1205) const
d88de032 1206{
3437f881 1207 return(*this);
6f38c86f 1208} // end of wxBitmap::GetBitmapForDC
d88de032 1209
3b9e3455
DW
1210// ----------------------------------------------------------------------------
1211// wxMask
1212// ----------------------------------------------------------------------------
0e320a79
DW
1213
1214wxMask::wxMask()
1215{
4f72fe4f 1216 m_hMaskBitmap = 0;
6f38c86f 1217} // end of wxMask::wxMask
0e320a79
DW
1218
1219// Construct a mask from a bitmap and a colour indicating
1220// the transparent area
4f72fe4f
DW
1221wxMask::wxMask(
1222 const wxBitmap& rBitmap
1223, const wxColour& rColour
1224)
0e320a79 1225{
4f72fe4f
DW
1226 m_hMaskBitmap = 0;
1227 Create( rBitmap
1228 ,rColour
1229 );
6f38c86f 1230} // end of wxMask::wxMask
0e320a79
DW
1231
1232// Construct a mask from a bitmap and a palette index indicating
1233// the transparent area
4f72fe4f
DW
1234wxMask::wxMask(
1235 const wxBitmap& rBitmap
1236, int nPaletteIndex
1237)
0e320a79 1238{
4f72fe4f
DW
1239 m_hMaskBitmap = 0;
1240 Create( rBitmap
1241 ,nPaletteIndex
1242 );
6f38c86f 1243} // end of wxMask::wxMask
0e320a79
DW
1244
1245// Construct a mask from a mono bitmap (copies the bitmap).
4f72fe4f
DW
1246wxMask::wxMask(
1247 const wxBitmap& rBitmap
1248)
0e320a79 1249{
4f72fe4f
DW
1250 m_hMaskBitmap = 0;
1251 Create(rBitmap);
6f38c86f 1252} // end of wxMask::wxMask
0e320a79
DW
1253
1254wxMask::~wxMask()
1255{
4f72fe4f
DW
1256 if (m_hMaskBitmap)
1257 ::GpiDeleteBitmap((HBITMAP)m_hMaskBitmap);
6f38c86f 1258} // end of wxMask::~wxMask
0e320a79
DW
1259
1260// Create a mask from a mono bitmap (copies the bitmap).
58b16424
DW
1261bool wxMask::Create(
1262 const wxBitmap& rBitmap
1263)
0e320a79 1264{
6f38c86f 1265 BITMAPINFOHEADER2 vBmih;
58b16424 1266 SIZEL vSize = {0, 0};
6f38c86f
DW
1267 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1268 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1269 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1270 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1271 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1272 POINTL vPoint[4] = { 0 ,0, rBitmap.GetWidth(), rBitmap.GetHeight(),
1273 0, 0, rBitmap.GetWidth(), rBitmap.GetHeight()
1274 };
58b16424
DW
1275
1276 if (m_hMaskBitmap)
3b9e3455 1277 {
58b16424
DW
1278 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1279 m_hMaskBitmap = 0;
3b9e3455 1280 }
58b16424 1281 if (!rBitmap.Ok() || rBitmap.GetDepth() != 1)
3b9e3455 1282 {
58b16424 1283 return(FALSE);
3b9e3455 1284 }
6f38c86f
DW
1285
1286 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1287 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1288 vBmih.cx = rBitmap.GetWidth();
1289 vBmih.cy = rBitmap.GetHeight();
1290 vBmih.cPlanes = 1;
1c9a789e 1291 vBmih.cBitCount = 24;
6f38c86f
DW
1292
1293 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
1294 ,&vBmih
1295 ,0L
1296 ,NULL
1297 ,NULL
1298 );
1299
1300 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
1301 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
1302 ::GpiBitBlt( hPSDst
1303 ,hPSSrc
1304 ,4L
1305 ,vPoint
1306 ,ROP_SRCCOPY
1307 ,BBO_IGNORE
1308 );
1309
1310 ::GpiDestroyPS(hPSSrc);
1311 ::GpiDestroyPS(hPSDst);
1312 ::DevCloseDC(hDCSrc);
1313 ::DevCloseDC(hDCDst);
58b16424 1314 return(TRUE);
6f38c86f 1315} // end of wxMask::Create
0e320a79
DW
1316
1317// Create a mask from a bitmap and a palette index indicating
1318// the transparent area
58b16424
DW
1319bool wxMask::Create(
1320 const wxBitmap& rBitmap
1321, int nPaletteIndex
1322)
0e320a79 1323{
58b16424 1324 if (m_hMaskBitmap)
3b9e3455 1325 {
58b16424
DW
1326 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1327 m_hMaskBitmap = 0;
3b9e3455 1328 }
58b16424 1329 if (rBitmap.Ok() && rBitmap.GetPalette()->Ok())
3b9e3455 1330 {
43543d98
DW
1331 unsigned char cRed;
1332 unsigned char cGreen;
1333 unsigned char cBlue;
1334
58b16424 1335 if (rBitmap.GetPalette()->GetRGB( nPaletteIndex
43543d98
DW
1336 ,&cRed
1337 ,&cGreen
1338 ,&cBlue
58b16424 1339 ))
3b9e3455 1340 {
43543d98
DW
1341 wxColour vTransparentColour( cRed
1342 ,cGreen
1343 ,cBlue
58b16424
DW
1344 );
1345
1346 return (Create( rBitmap
1347 ,vTransparentColour
1348 ));
3b9e3455
DW
1349 }
1350 }
58b16424 1351 return(FALSE);
6f38c86f 1352} // end of wxMask::Create
0e320a79
DW
1353
1354// Create a mask from a bitmap and a colour indicating
1355// the transparent area
58b16424
DW
1356bool wxMask::Create(
1357 const wxBitmap& rBitmap
1358, const wxColour& rColour
1359)
0e320a79 1360{
6f38c86f
DW
1361 bool bOk = TRUE;
1362 COLORREF vMaskColour = OS2RGB( rColour.Red()
1363 ,rColour.Green()
1364 ,rColour.Blue()
1365 );
1366 BITMAPINFOHEADER2 vBmih;
58b16424 1367 SIZEL vSize = {0, 0};
6f38c86f
DW
1368 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1369 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1370 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1371 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1372 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1373 POINTL vPoint[4] = { 0 ,0, rBitmap.GetWidth(), rBitmap.GetHeight(),
1374 0, 0, rBitmap.GetWidth(), rBitmap.GetHeight()
1375 };
58b16424
DW
1376
1377 if (m_hMaskBitmap)
3b9e3455 1378 {
58b16424
DW
1379 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1380 m_hMaskBitmap = 0;
3b9e3455 1381 }
58b16424 1382 if (!rBitmap.Ok())
3b9e3455 1383 {
58b16424 1384 return(FALSE);
3b9e3455
DW
1385 }
1386
6f38c86f
DW
1387 //
1388 // Scan the bitmap for the transparent colour and set
3b9e3455
DW
1389 // the corresponding pixels in the mask to BLACK and
1390 // the rest to WHITE
6f38c86f
DW
1391 //
1392
1393 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1394 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1395 vBmih.cx = rBitmap.GetWidth();
1396 vBmih.cy = rBitmap.GetHeight();
1397 vBmih.cPlanes = 1;
1398 vBmih.cBitCount = 1;
1399
1400 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
1401 ,&vBmih
1402 ,0L
1403 ,NULL
1404 ,NULL
1405 );
1406
1407 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
1408 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
1409
1410 //
1411 // This is not very efficient, but I can't think
3b9e3455 1412 // of a better way of doing it
6f38c86f 1413 //
58b16424 1414 for (int w = 0; w < rBitmap.GetWidth(); w++)
3b9e3455 1415 {
58b16424 1416 for (int h = 0; h < rBitmap.GetHeight(); h++)
3b9e3455 1417 {
6f38c86f
DW
1418 POINTL vPt = {w, h};
1419 COLORREF vCol = (COLORREF)::GpiQueryPel(hPSSrc, &vPt);
1420 if (vCol == (COLORREF)CLR_NOINDEX)
1421 {
1422 //
1423 // Doesn't make sense to continue
1424 //
1425 bOk = FALSE;
1426 break;
1427 }
58b16424 1428
6f38c86f 1429 if (vCol == vMaskColour)
3b9e3455 1430 {
6f38c86f
DW
1431 ::GpiSetColor(hPSDst, OS2RGB(0, 0, 0));
1432 ::GpiSetPel(hPSDst, &vPt);
3b9e3455
DW
1433 }
1434 else
1435 {
6f38c86f
DW
1436 ::GpiSetColor(hPSDst, OS2RGB(255, 255, 255));
1437 ::GpiSetPel(hPSDst, &vPt);
3b9e3455
DW
1438 }
1439 }
1440 }
6f38c86f
DW
1441 ::GpiSetBitmap(hPSSrc, NULL);
1442 ::GpiSetBitmap(hPSDst, NULL);
1443 ::GpiDestroyPS(hPSSrc);
1444 ::GpiDestroyPS(hPSDst);
1445 ::DevCloseDC(hDCSrc);
1446 ::DevCloseDC(hDCDst);
58b16424 1447 return(TRUE);
6f38c86f 1448} // end of wxMask::Create
0e320a79 1449
3b9e3455
DW
1450// ----------------------------------------------------------------------------
1451// wxBitmapHandler
1452// ----------------------------------------------------------------------------
0e320a79 1453
58b16424
DW
1454bool wxBitmapHandler::Create(
1455 wxGDIImage* pImage
1456, void* pData
1457, long lFlags
1458, int nWidth
1459, int nHeight
1460, int nDepth
1461)
3b9e3455 1462{
58b16424
DW
1463 wxBitmap* pBitmap = wxDynamicCast( pImage
1464 ,wxBitmap
1465 );
3b9e3455 1466
58b16424
DW
1467 return(pBitmap ? Create( pBitmap
1468 ,pData
1469 ,nWidth
1470 ,nHeight
1471 ,nDepth
1472 ) : FALSE);
3b9e3455
DW
1473}
1474
58b16424
DW
1475bool wxBitmapHandler::Load(
1476 wxGDIImage* pImage
3029781e 1477, int nId
58b16424
DW
1478, long lFlags
1479, int nWidth
1480, int nHeight
1481)
3b9e3455 1482{
43543d98
DW
1483 wxBitmap* pBitmap = wxDynamicCast( pImage
1484 ,wxBitmap
1485 );
3b9e3455 1486
58b16424 1487 return(pBitmap ? LoadFile( pBitmap
3029781e 1488 ,nId
58b16424
DW
1489 ,lFlags
1490 ,nWidth
1491 ,nHeight
1492 ) : FALSE);
3b9e3455
DW
1493}
1494
58b16424
DW
1495bool wxBitmapHandler::Save(
1496 wxGDIImage* pImage
1497, const wxString& rName
1498, int lType
1499)
0e320a79 1500{
58b16424
DW
1501 wxBitmap* pBitmap = wxDynamicCast( pImage
1502 ,wxBitmap
1503 );
0e320a79 1504
58b16424
DW
1505 return(pBitmap ? SaveFile( pBitmap
1506 ,rName
1507 ,lType
1508 ) : FALSE);
0e320a79
DW
1509}
1510
58b16424
DW
1511bool wxBitmapHandler::Create(
1512 wxBitmap* WXUNUSED(pBitmap)
1513, void* WXUNUSED(pData)
1514, long WXUNUSED(lType)
1515, int WXUNUSED(nWidth)
1516, int WXUNUSED(nHeight)
1517, int WXUNUSED(nDepth)
1518)
0e320a79 1519{
58b16424 1520 return(FALSE);
0e320a79
DW
1521}
1522
58b16424
DW
1523bool wxBitmapHandler::LoadFile(
1524 wxBitmap* WXUNUSED(pBitmap)
3029781e 1525, int WXUNUSED(nId)
58b16424
DW
1526, long WXUNUSED(lType)
1527, int WXUNUSED(nDesiredWidth)
1528, int WXUNUSED(nDesiredHeight)
1529)
0e320a79 1530{
43543d98 1531 return(FALSE);
0e320a79
DW
1532}
1533
58b16424
DW
1534bool wxBitmapHandler::SaveFile(
1535 wxBitmap* WXUNUSED(pBitmap)
1536, const wxString& WXUNUSED(rName)
1537, int WXUNUSED(nType)
1538, const wxPalette* WXUNUSED(pPalette)
1539)
0e320a79 1540{
58b16424 1541 return(FALSE);
0e320a79 1542}
ce44c50e 1543
020a1653
DW
1544// ----------------------------------------------------------------------------
1545// Utility functions
1546// ----------------------------------------------------------------------------
1547HBITMAP wxInvertMask(
1548 HBITMAP hBmpMask
1549, int nWidth
1550, int nHeight
1551)
1552{
1553 HBITMAP hBmpInvMask = 0;
1554
1555 wxCHECK_MSG( hBmpMask, 0, _T("invalid bitmap in wxInvertMask") );
1556
1557 //
1558 // Get width/height from the bitmap if not given
1559 //
1560 if (!nWidth || !nHeight)
1561 {
1562 BITMAPINFOHEADER2 vBmhdr;
1563
1564 ::GpiQueryBitmapInfoHeader( hBmpMask
1565 ,&vBmhdr
1566 );
1567 nWidth = (int)vBmhdr.cx;
e464c180 1568 nHeight = (int)vBmhdr.cy;
020a1653
DW
1569 }
1570
1571 BITMAPINFOHEADER2 vBmih;
1572 SIZEL vSize = {0, 0};
1573 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
e464c180
DW
1574 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1575 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1576 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1577 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1578 POINTL vPoint[4] = { 0 ,0, nWidth, nHeight,
1579 0, 0, nWidth, nHeight
020a1653
DW
1580 };
1581
1c9a789e
DW
1582 memset(&vBmih, '\0', 16);
1583 vBmih.cbFix = 16;
e464c180
DW
1584 vBmih.cx = nWidth;
1585 vBmih.cy = nHeight;
020a1653 1586 vBmih.cPlanes = 1;
1c9a789e 1587 vBmih.cBitCount = 24;
020a1653
DW
1588
1589 hBmpInvMask = ::GpiCreateBitmap( hPSDst
1590 ,&vBmih
1591 ,0L
1592 ,NULL
1593 ,NULL
1594 );
1595
1596 ::GpiSetBitmap(hPSSrc, (HBITMAP) hBmpMask);
1597 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpInvMask);
1598
1599 ::GpiBitBlt( hPSDst
1600 ,hPSSrc
1601 ,4L
e464c180 1602 ,vPoint
8e8d8eef 1603 ,ROP_SRCINVERT
020a1653
DW
1604 ,BBO_IGNORE
1605 );
1606
1607 ::GpiDestroyPS(hPSSrc);
1608 ::GpiDestroyPS(hPSDst);
1609 ::DevCloseDC(hDCSrc);
e464c180 1610 ::DevCloseDC(hDCDst);
020a1653
DW
1611
1612 return hBmpInvMask;
1613} // end of WxWinGdi_InvertMask
3437f881 1614