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