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