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