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