bitmap and image updates
[wxWidgets.git] / src / os2 / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: bitmap.cpp
3 // Purpose: wxBitmap
4 // Author: David Webster
5 // Modified by:
6 // Created: 08/08/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include <stdio.h>
17
18 #include "wx/list.h"
19 #include "wx/utils.h"
20 #include "wx/app.h"
21 #include "wx/palette.h"
22 #include "wx/dcmemory.h"
23 #include "wx/bitmap.h"
24 #include "wx/icon.h"
25 #endif
26
27 #include "wx/os2/private.h"
28 #include "wx/log.h"
29
30 //#include "wx/msw/dib.h"
31 #include "wx/image.h"
32
33 // ----------------------------------------------------------------------------
34 // macros
35 // ----------------------------------------------------------------------------
36
37 #if !USE_SHARED_LIBRARIES
38 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
39 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
40
41 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
42 #endif
43
44 // ============================================================================
45 // implementation
46 // ============================================================================
47
48 // ----------------------------------------------------------------------------
49 // wxBitmapRefData
50 // ----------------------------------------------------------------------------
51
52 wxBitmapRefData::wxBitmapRefData()
53 {
54 m_nQuality = 0;
55 m_pSelectedInto = NULL;
56 m_nNumColors = 0;
57 m_pBitmapMask = NULL;
58 }
59
60 void wxBitmapRefData::Free()
61 {
62 wxASSERT_MSG( !m_pSelectedInto,
63 wxT("deleting bitmap still selected into wxMemoryDC") );
64
65 if (m_hBitmap)
66 {
67 if ( !::GpiDeleteBitmap((HBITMAP)m_hBitmap) )
68 {
69 wxLogLastError("GpiDeleteBitmap(hbitmap)");
70 }
71 }
72
73 delete m_pBitmapMask;
74 m_pBitmapMask = NULL;
75 }
76
77 // ----------------------------------------------------------------------------
78 // wxBitmap creation
79 // ----------------------------------------------------------------------------
80
81 // this function should be called from all wxBitmap ctors
82 void wxBitmap::Init()
83 {
84 // m_refData = NULL; done in the base class ctor
85
86 if (wxTheBitmapList)
87 wxTheBitmapList->AddBitmap(this);
88 }
89
90 bool wxBitmap::CopyFromIconOrCursor(
91 const wxGDIImage& rIcon
92 )
93 {
94 wxBitmapRefData* pRefData = new wxBitmapRefData;
95
96 m_refData = pRefData;
97
98 refData->m_width = rIcon.GetWidth();
99 refData->m_height = rIcon.GetHeight();
100 refData->m_depth = wxDisplayDepth();
101
102 refData->m_hBitmap = (WXHBITMAP)rIcon.GetHandle();
103 // no mask???
104 refData->m_bitmapMask = new wxMask();
105
106 #if WXWIN_COMPATIBILITY_2
107 refData->m_ok = TRUE;
108 #endif // WXWIN_COMPATIBILITY_2
109
110 return(TRUE);
111 }
112
113 bool wxBitmap::CopyFromCursor(
114 const wxCursor& rCursor
115 )
116 {
117 UnRef();
118
119 if (!rCursor.Ok())
120 return(FALSE);
121 return CopyFromIconOrCursor(wxGDIImage)rCursor);
122 }
123
124 bool wxBitmap::CopyFromIcon(
125 const wxIcon& rIcon
126 )
127 {
128 UnRef();
129
130 if (!rIcon.Ok())
131 return(FALSE);
132
133 #if WXWIN_COMPATIBILITY_2
134 refData->m_ok = TRUE;
135 #endif // WXWIN_COMPATIBILITY_2
136
137 return CopyFromIconOrCursor(icon);
138 }
139
140 wxBitmap::~wxBitmap()
141 {
142 if (wxTheBitmapList)
143 wxTheBitmapList->DeleteObject(this);
144 }
145
146 wxBitmap::wxBitmap(
147 const char zBits[]
148 , int nTheWidth
149 , int nTheHeight
150 , int nNoBits
151 )
152 {
153 Init();
154
155 wxBitmapRefData* pRefData = new wxBitmapRefData;
156 BITMAPINFOHEADER2 vHeader;
157 BITMAPINFO2 vInfo;
158 HDC hDc;
159 HPS hPs;
160 DEVOPENSTRUCT vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
161 SIZEL vSize = {0, 0};
162
163 wxAssert(vHabmain != NULL);
164
165 hDc = ::DevOpenDC(vHabmain, OD_MEMORY, (PSZ)"*", 1L, (PDEVOPENDATA)&vDop, 0L);
166
167 vHeader.cbFix = sizeof(vHeader);
168 vHeader.cx = (USHORT)nTheWidth;
169 vHeader.cy = (USHORT)nTheHeight;
170 vHeader.cPlanes = 1L;
171 vHeader.cBitCount = nNoBits;
172 vHeader.ulCompression = BCA_UNCOMP;
173 vHeader.cxResolution = 0;
174 vHeader.cyResolution = 0;
175 vHeader.cclrUsed = 0;
176 vHeader.cclrImportant = 0;
177 vHeader.usUnits = BRU_METRIC;
178 vHeader.usRecording = BRA_BOTTOMUP;
179 vHeader.usRendering = BRH_NOTHALFTONED;
180 vHeader.cSize1 = 0;
181 vHeader.cSize2 = 0;
182 vHeader.ulColorEncoding = 0;
183 vHeader.ulIdentifier = 0;
184
185 hPs = ::GpiCreatePS(vHabMain, hdc, &vSize, GPIA_ASSOC | PU_PELS);
186 if (hPs == 0)
187 {
188 wxLogLastError("GpiCreatePS Failure");
189 }
190
191 m_hDc = hDc;
192 m_hPs = hPs;
193
194 m_refData = pRefData;
195
196 refData->m_width = nTheWidth;
197 refData->m_height = nTheHeight;
198 refData->m_depth = nNoBits;
199 refData->m_numColors = 0;
200 refData->m_selectedInto = NULL;
201
202 HBITMAP hBmp = ::GpiCreateBitmap(hPs, &vHeader, 0L, NULL, &vInfo);
203 if ( !hbmp )
204 {
205 wxLogLastError("CreateBitmap");
206 }
207 SetHBITMAP((WXHBITMAP)hbmp);
208 }
209
210 // Create from XPM data
211 wxBitmap::wxBitmap(
212 char** ppData
213 , wxControl* WXUNUSED(pAnItem))
214 {
215 Init();
216
217 F (void)Create( (void *)ppData
218 ,wxBITMAP_TYPE_XPM_DATA
219 ,0
220 ,0
221 ,0
222 );
223 }
224
225 wxBitmap::wxBitmap(
226 int nW
227 , int nH
228 , int nD
229 )
230 {
231 Init();
232
233 (void)Create( nW
234 ,nH
235 ,nD
236 );
237 }
238
239 wxBitmap::wxBitmap(
240 void* pData
241 , long lType
242 , int nWidth
243 , int nHeight
244 , int nDepth
245 )
246 {
247 Init();
248
249 (void)Create( pData
250 ,lType
251 ,nWidth
252 ,nHeight
253 ,nDepth
254 );
255 }
256
257 wxBitmap::wxBitmap(
258 const wxString& rFilename
259 , long lType
260 )
261 {
262 Init();
263
264 LoadFile( rFilename
265 ,(int)lType
266 );
267 }
268
269 bool wxBitmap::Create(
270 int nW
271 , int nH
272 , int nD
273 )
274 {
275 HBITMAP hBmp;
276 BITMAPINFOHEADER2 vHeader;
277 BITMAPINFO2 vInfo;
278 HPS hpsScreen;
279 HDC hdcScreen;
280 DEVOPENSTRUCT vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
281 SIZEL vSize = {0, 0};
282 LONG lBitCount;
283
284 wxAssert(vHabmain != NULL);
285
286 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
287 hdcScreen = ::GpiQueryDevice(hpsScreen);
288 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, &lBitCount);
289
290 vHeader.cbFix = sizeof(vHeader);
291 vHeader.cx = (USHORT)nW;
292 vHeader.cy = (USHORT)nH;
293 vHeader.cPlanes = (USHORT)nD;
294 vHeader.cBitCount = lBitCount;
295 vHeader.ulCompression = BCA_UNCOMP;
296 vHeader.cxResolution = 0;
297 vHeader.cyResolution = 0;
298 vHeader.cclrUsed = 0;
299 vHeader.cclrImportant = 0;
300 vHeader.usUnits = BRU_METRIC;
301 vHeader.usRecording = BRA_BOTTOMUP;
302 vHeader.usRendering = BRH_NOTHALFTONED;
303 vHeader.cSize1 = 0;
304 vHeader.cSize2 = 0;
305 vHeader.ulColorEncoding = 0;
306 vHeader.ulIdentifier = 0;
307
308
309 UnRef();
310 m_refData = new wxBitmapRefData;
311
312 GetBitmapData()->m_width = nW;
313 GetBitmapData()->m_height = nH;
314 GetBitmapData()->m_depth = nD;
315
316 if (nD > 0)
317 {
318 hBmp = ::GpiCreateBitmap(hpsScreen, &vHeader, 0L, NULL, &vInfo);
319 if (!hBmp)
320 {
321 wxLogLastError("CreateBitmap");
322 }
323 }
324 else
325 {
326 LONG lPlanes;
327
328 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, &lPlanes);
329 hBmp = ::GpiCreateBitmap(hpsScreen, &vHeader, 0L, NULL, &vInfo);
330 if (!hBmp)
331 {
332 wxLogLastError("CreateBitmap");
333 }
334 GetBitmapData()->m_depth = wxDisplayDepth();
335 }
336 SetHBITMAP((WXHBITMAP)hBmp);
337
338 #if WXWIN_COMPATIBILITY_2
339 GetBitmapData()->m_bOk = hBmp != 0;
340 #endif // WXWIN_COMPATIBILITY_2
341
342 return Ok();
343 }
344
345 bool wxBitmap::LoadFile(
346 const wxString& rFilename
347 , long lType
348 )
349 {
350 UnRef();
351
352 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
353 ,wxBitmapHandler
354 );
355
356 if (pHandler)
357 {
358 m_refData = new wxBitmapRefData;
359
360 return(pHandler->LoadFile( this
361 ,rFilename
362 ,lType
363 , -1
364 , -1
365 );
366 }
367 else
368 {
369 wxImage vImage;
370
371 if (!vImage.LoadFile(rFilename, lType) || !image.Ok() )
372 return(FALSE);
373
374 *this = vImage.ConvertToBitmap();
375
376 return(TRUE);
377 }
378 }
379
380 bool wxBitmap::Create(
381 void* pData
382 , long lType
383 , int nWidth
384 , int nHeight
385 , int nDepth
386 )
387 {
388 UnRef();
389
390 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
391 ,wxBitmapHandler
392 );
393
394 if (!pHandler)
395 {
396 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
397 "type %d defined."), type);
398
399 return(FALSE);
400 }
401
402 m_refData = new wxBitmapRefData;
403
404 return(handler->Create( this
405 ,pData
406 ,lType
407 ,nWidth
408 ,nHeight
409 ,nDepth
410 ));
411 }
412
413 bool wxBitmap::SaveFile(
414 const wxString& rFilename
415 , int lType
416 , const wxPalette* pPalette
417 )
418 {
419 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
420 ,wxBitmapHandler
421 );
422
423 if (pHandler)
424 {
425 return pHandler->SaveFile( this
426 ,rFilename
427 ,lType
428 ,pPalette
429 );
430 }
431 else
432 {
433 // FIXME what about palette? shouldn't we use it?
434 wxImage vImage(*this);
435
436 if (!vImage.Ok())
437 return(FALSE);
438
439 return(vImage.SaveFile( rFilename
440 ,lType
441 ));
442 }
443 }
444
445 // ----------------------------------------------------------------------------
446 // wxBitmap accessors
447 // ----------------------------------------------------------------------------
448
449 void wxBitmap::SetQuality(
450 int nQ
451 )
452 {
453 EnsureHasData();
454
455 GetBitmapData()->m_nQuality = nQ;
456 }
457
458 #if WXWIN_COMPATIBILITY_2
459 void wxBitmap::SetOk(
460 bool bOk
461 )
462 {
463 EnsureHasData();
464
465 GetBitmapData()->m_bOk = bOk;
466 }
467 #endif // WXWIN_COMPATIBILITY_2
468
469 void wxBitmap::SetPalette(
470 const wxPalette& rPalette
471 )
472 {
473 EnsureHasData();
474
475 GetBitmapData()->m_vBitmapPalette = rPalette;
476 }
477
478 void wxBitmap::SetMask(
479 wxMask* pMask
480 )
481 {
482 EnsureHasData();
483
484 GetBitmapData()->m_pBitmapMask = pMask;
485 }
486
487 // Will try something for OS/2 but not really sure how close
488 // to the msw intent this is.
489 wxBitmap wxBitmap::GetBitmapForDC(
490 wxDC& rDc
491 ) const
492 {
493 wxMemoryDC vMemDC;
494 wxBitmap vTmpBitmap( this->GetWidth()
495 ,this->GetHeight()
496 ,rDc.GetDepth()
497 );
498 HPS hMemoryPS;
499 HPS hPs;
500 POINTL vPoint[4];
501 SIZEL vSize = {0,0}
502
503 hMemoryPS = ::GpiCreatePS(habMain, (HDC)vMemDC.m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPI_ASSOC);
504 hPs = ::GpiCreatePS(habMain, (HDC)rDc.m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPI_ASSOC);
505
506 // TODO: Set the points
507
508 rDc.m_oldBitmap = (WXHBITMAP)::GpiSetBitMap(hPs, (HBITMAP)vTmpBitmap.GetHBITMAP());
509 :GpiBitBlt(hPs, hMemoryPS, 4L, vPoint, ROP_SRCCOPY | BBO_IGNORE);
510
511 return(vTmpBitmap);
512 }
513
514 // ----------------------------------------------------------------------------
515 // wxMask
516 // ----------------------------------------------------------------------------
517
518 wxMask::wxMask()
519 {
520 m_hMaskBitmap = 0;
521 }
522
523 // Construct a mask from a bitmap and a colour indicating
524 // the transparent area
525 wxMask::wxMask(
526 const wxBitmap& rBitmap
527 , const wxColour& rColour
528 )
529 {
530 m_hMaskBitmap = 0;
531 Create( rBitmap
532 ,rColour
533 );
534 }
535
536 // Construct a mask from a bitmap and a palette index indicating
537 // the transparent area
538 wxMask::wxMask(
539 const wxBitmap& rBitmap
540 , int nPaletteIndex
541 )
542 {
543 m_hMaskBitmap = 0;
544 Create( rBitmap
545 ,nPaletteIndex
546 );
547 }
548
549 // Construct a mask from a mono bitmap (copies the bitmap).
550 wxMask::wxMask(
551 const wxBitmap& rBitmap
552 )
553 {
554 m_hMaskBitmap = 0;
555 Create(rBitmap);
556 }
557
558 wxMask::~wxMask()
559 {
560 if (m_hMaskBitmap)
561 ::GpiDeleteBitmap((HBITMAP)m_hMaskBitmap);
562 }
563
564 // Create a mask from a mono bitmap (copies the bitmap).
565 bool wxMask::Create(
566 const wxBitmap& rBitmap
567 )
568 {
569 BITMAPINFOHEADER2 vHeader;
570 DEVOPENSTRUCT vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
571 SIZEL vSize = {0, 0};
572 POINTL vPoint[4];
573
574 if (m_hMaskBitmap)
575 {
576 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
577 m_hMaskBitmap = 0;
578 }
579 if (!rBitmap.Ok() || rBitmap.GetDepth() != 1)
580 {
581 return(FALSE);
582 }
583 vHeader.cbFix = sizeof(vHeader);
584 vHeader.cx = (USHORT)rBitmap.GetWidth();
585 vHeader.cy = (USHORT)rBitmap.GetHeight();
586 vHeader.cPlanes = 1;
587 vHeader.cBitCount = 1;
588
589 m_hMaskBitmap = (WXHBITMAP) ::GpiCreateBitmap( m_hPs
590 ,&vHeader
591 ,0L
592 ,NULL
593 ,NULL
594 );
595
596 HPS srcPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
597 ::GpiSetBitmap(srcPS, (HBITMAP)rBitmap.GetHBITMAP());
598 HPS destPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
599 ::GpiSetBitmap(srcPS, (HBITMAP)m_hMaskBitmap);
600 // TODO: Set the point array
601 :GpiBitBlt(destPs, srcPS, 4L, vPoint, ROP_SRCCOPY | BBO_IGNORE);
602
603 ::GpiDestroyPS(srcPS);
604 ::GpiDestroyPS(destPS);
605 return(TRUE);
606 }
607
608 // Create a mask from a bitmap and a palette index indicating
609 // the transparent area
610 bool wxMask::Create(
611 const wxBitmap& rBitmap
612 , int nPaletteIndex
613 )
614 {
615 if (m_hMaskBitmap)
616 {
617 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
618 m_hMaskBitmap = 0;
619 }
620 if (rBitmap.Ok() && rBitmap.GetPalette()->Ok())
621 {
622 unsigned char red, green, blue;
623 if (rBitmap.GetPalette()->GetRGB( nPaletteIndex
624 ,&rRed
625 ,&rGreen
626 ,&rBlue
627 ))
628 {
629 wxColour vTransparentColour( rRed
630 ,rGreen
631 ,rBlue
632 );
633
634 return (Create( rBitmap
635 ,vTransparentColour
636 ));
637 }
638 }
639 return(FALSE);
640 }
641
642 // Create a mask from a bitmap and a colour indicating
643 // the transparent area
644 bool wxMask::Create(
645 const wxBitmap& rBitmap
646 , const wxColour& rColour
647 )
648 {
649 BITMAPINFOHEADER2 vHeader;
650 DEVOPENSTRUCT vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
651 SIZEL vSize = {0, 0};
652 POINTL vPoint[4];
653
654 if (m_hMaskBitmap)
655 {
656 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
657 m_hMaskBitmap = 0;
658 }
659 if (!rBitmap.Ok())
660 {
661 return(FALSE);
662 }
663
664 // scan the bitmap for the transparent colour and set
665 // the corresponding pixels in the mask to BLACK and
666 // the rest to WHITE
667 COLORREF vMaskColour = OS2RGB(rColour.Red(), rColour.Green(), rColour.Blue());
668
669 vHeader.cbFix = sizeof(vHeader);
670 vHeader.cx = (USHORT)rBitmap.GetWidth();
671 vHeader.cy = (USHORT)rBitmap.GetHeight();
672 vHeader.cPlanes = 1;
673 vHeader.cBitCount = 1;
674
675 m_hMaskBitmap = (WXHBITMAP) ::GpiCreateBitmap( m_hPs
676 ,&vHeader
677 ,0L
678 ,NULL
679 ,NULL
680 );
681 );
682 HPS srcPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
683 ::GpiSetBitmap(srcPS, (HBITMAP)rBitmap.GetHBITMAP());
684 HPS destPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
685 ::GpiSetBitmap(srcPS, (HBITMAP)m_hMaskBitmap);
686
687 // this is not very efficient, but I can't think
688 // of a better way of doing it
689 for (int w = 0; w < rBitmap.GetWidth(); w++)
690 {
691 for (int h = 0; h < rBitmap.GetHeight(); h++)
692 {
693 POINTL vPoint;
694
695 vPoint.x = w;
696 vPoint.y = h;
697
698 COLORREF col = ::GpiQueryPel(srcPS, w, h);
699
700 if (col == vMaskColour)
701 {
702 ::GpiSetColor(destPS, CLR_WHITE);
703 ::GpiSetPel(destPS, &vPoint);
704 }
705 else
706 {
707 ::GpiSetColor(destPS, CLR_BLACK);
708 ::GpiSetPel(destPS, &vPoint);
709 }
710 }
711 }
712 ::GpiDestroyPS(srcPS);
713 ::GpiDestroyPS(destPS);
714 return(TRUE);
715 }
716
717 // ----------------------------------------------------------------------------
718 // wxBitmapHandler
719 // ----------------------------------------------------------------------------
720
721 bool wxBitmapHandler::Create(
722 wxGDIImage* pImage
723 , void* pData
724 , long lFlags
725 , int nWidth
726 , int nHeight
727 , int nDepth
728 )
729 {
730 wxBitmap* pBitmap = wxDynamicCast( pImage
731 ,wxBitmap
732 );
733
734 return(pBitmap ? Create( pBitmap
735 ,pData
736 ,nWidth
737 ,nHeight
738 ,nDepth
739 ) : FALSE);
740 }
741
742 bool wxBitmapHandler::Load(
743 wxGDIImage* pImage
744 , const wxString& rName
745 , long lFlags
746 , int nWidth
747 , int nHeight
748 )
749 {
750 wxBitmap* bitmap = wxDynamicCast( pImage
751 ,wxBitmap
752 );
753
754 return(pBitmap ? LoadFile( pBitmap
755 ,rName
756 ,lFlags
757 ,nWidth
758 ,nHeight
759 ) : FALSE);
760 }
761
762 bool wxBitmapHandler::Save(
763 wxGDIImage* pImage
764 , const wxString& rName
765 , int lType
766 )
767 {
768 wxBitmap* pBitmap = wxDynamicCast( pImage
769 ,wxBitmap
770 );
771
772 return(pBitmap ? SaveFile( pBitmap
773 ,rName
774 ,lType
775 ) : FALSE);
776 }
777
778 bool wxBitmapHandler::Create(
779 wxBitmap* WXUNUSED(pBitmap)
780 , void* WXUNUSED(pData)
781 , long WXUNUSED(lType)
782 , int WXUNUSED(nWidth)
783 , int WXUNUSED(nHeight)
784 , int WXUNUSED(nDepth)
785 )
786 {
787 return(FALSE);
788 }
789
790 bool wxBitmapHandler::LoadFile(
791 wxBitmap* WXUNUSED(pBitmap)
792 , const wxString& WXUNUSED(rName)
793 , long WXUNUSED(lType)
794 , int WXUNUSED(nDesiredWidth)
795 , int WXUNUSED(nDesiredHeight)
796 )
797 {
798 return(FALSE(;
799 }
800
801 bool wxBitmapHandler::SaveFile(
802 wxBitmap* WXUNUSED(pBitmap)
803 , const wxString& WXUNUSED(rName)
804 , int WXUNUSED(nType)
805 , const wxPalette* WXUNUSED(pPalette)
806 )
807 {
808 return(FALSE);
809 }
810