1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "bitmap.h"
17 #define XtParent XTPARENT
22 #include "wx/palette.h"
23 #include "wx/bitmap.h"
26 #include "wx/dcmemory.h"
32 #pragma message disable nosimpint
36 #pragma message enable nosimpint
41 #include <X11/Intrinsic.h>
49 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
50 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
52 wxBitmapRefData::wxBitmapRefData()
62 m_pixmap
= (WXPixmap
) 0;
63 m_display
= (WXDisplay
*) 0;
65 // m_freePixmap = TRUE; //TODO: necessary?
67 m_freeColors
= (unsigned long*) 0;
68 m_freeColorsCount
= 0;
71 // These 5 variables are for wxControl
73 m_insensPixmap
= (WXPixmap
) 0;
74 m_labelPixmap
= (WXPixmap
) 0;
75 m_armPixmap
= (WXPixmap
) 0;
78 m_image
= (WXImage
*) 0;
79 m_insensImage
= (WXImage
*) 0;
83 wxBitmapRefData::~wxBitmapRefData()
87 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_labelPixmap
);
90 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_armPixmap
);
93 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_insensPixmap
);
99 XmUninstallImage ((XImage
*) m_image
);
100 XtFree ((char *) (XImage
*) m_image
);
107 XmUninstallImage ((XImage
*) m_insensImage
);
108 delete[] ((XImage
*) m_insensImage
)->data
;
109 XtFree ((char *) (XImage
*) m_insensImage
);
112 if (m_pixmap
/* && m_freePixmap */)
113 XFreePixmap ((Display
*) m_display
, (Pixmap
) m_pixmap
);
118 int screen
= DefaultScreen((Display
*) m_display
);
119 Colormap cmp
= DefaultColormap((Display
*) m_display
,screen
);
121 for(llp
= 0;llp
< m_freeColorsCount
;llp
++)
122 XFreeColors((Display
*) m_display
, cmp
, &m_freeColors
[llp
], 1, 0L);
132 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
139 wxBitmap::~wxBitmap()
143 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
145 m_refData
= new wxBitmapRefData
;
147 (void) Create((void*) bits
, wxBITMAP_TYPE_XBM_DATA
, width
, height
, depth
);
150 wxBitmap::wxBitmap(int w
, int h
, int d
)
152 (void)Create(w
, h
, d
);
155 wxBitmap::wxBitmap(void *data
, wxBitmapType type
,
156 int width
, int height
, int depth
)
158 (void) Create(data
, type
, width
, height
, depth
);
161 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
)
163 LoadFile(filename
, type
);
167 // Create from XPM data
168 static wxControl
* sg_Control
= NULL
;
169 wxBitmap::wxBitmap(char **data
, wxControl
* control
)
171 // Pass the control to the Create function using a global
172 sg_Control
= control
;
174 (void) Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
176 sg_Control
= (wxControl
*) NULL
;
180 bool wxBitmap::CreateFromXpm(const char **bits
)
182 wxCHECK_MSG( bits
, FALSE
, _T("NULL pointer in wxBitmap::CreateFromXpm") );
184 return Create(bits
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
187 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
193 bool wxBitmap::Create(int w
, int h
, int d
)
197 m_refData
= new wxBitmapRefData
;
200 d
= wxDisplayDepth();
202 M_BITMAPDATA
->m_width
= w
;
203 M_BITMAPDATA
->m_height
= h
;
204 M_BITMAPDATA
->m_depth
= d
;
205 // M_BITMAPDATA->m_freePixmap = TRUE;
207 Display
*dpy
= (Display
*) wxGetDisplay();
209 M_BITMAPDATA
->m_display
= dpy
; /* MATTHEW: [4] Remember the display */
211 M_BITMAPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
214 M_BITMAPDATA
->m_ok
= (M_BITMAPDATA
->m_pixmap
!= (WXPixmap
) 0) ;
215 return M_BITMAPDATA
->m_ok
;
218 bool wxBitmap::LoadFile(const wxString
& filename
, wxBitmapType type
)
222 m_refData
= new wxBitmapRefData
;
224 wxBitmapHandler
*handler
= FindHandler(type
);
226 if ( handler
== NULL
) {
228 if (!image
.LoadFile( filename
, type
)) return FALSE
;
231 *this = wxBitmap(image
);
237 return handler
->LoadFile(this, filename
, type
, -1, -1);
240 bool wxBitmap::Create(void *data
, wxBitmapType type
,
241 int width
, int height
, int depth
)
245 m_refData
= new wxBitmapRefData
;
247 wxBitmapHandler
*handler
= FindHandler(type
);
249 if ( handler
== NULL
) {
250 wxLogWarning("no data bitmap handler for type %ld defined.",
256 return handler
->Create(this, data
, type
, width
, height
, depth
);
259 bool wxBitmap::SaveFile(const wxString
& filename
, wxBitmapType type
,
260 const wxPalette
*palette
) const
262 wxBitmapHandler
*handler
= FindHandler(type
);
264 if ( handler
== NULL
) { // try wxImage
265 wxImage image
= this->ConvertToImage();
266 if (image
.Ok()) return image
.SaveFile( filename
, type
);
270 return handler
->SaveFile(this, filename
, type
, palette
);
273 void wxBitmap::SetWidth(int w
)
276 m_refData
= new wxBitmapRefData
;
278 M_BITMAPDATA
->m_width
= w
;
281 void wxBitmap::SetHeight(int h
)
284 m_refData
= new wxBitmapRefData
;
286 M_BITMAPDATA
->m_height
= h
;
289 void wxBitmap::SetDepth(int d
)
292 m_refData
= new wxBitmapRefData
;
294 M_BITMAPDATA
->m_depth
= d
;
300 void wxBitmap::SetQuality(int q
)
303 m_refData
= new wxBitmapRefData
;
305 M_BITMAPDATA
->m_quality
= q
;
310 void wxBitmap::SetOk(bool isOk
)
313 m_refData
= new wxBitmapRefData
;
315 M_BITMAPDATA
->m_ok
= isOk
;
318 void wxBitmap::SetPalette(const wxPalette
& palette
)
321 m_refData
= new wxBitmapRefData
;
323 M_BITMAPDATA
->m_bitmapPalette
= palette
;
326 void wxBitmap::SetMask(wxMask
*mask
)
329 m_refData
= new wxBitmapRefData
;
331 M_BITMAPDATA
->m_bitmapMask
= mask
;
334 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
337 (rect
.x
>= 0) && (rect
.y
>= 0) &&
338 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) && (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
339 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
341 wxBitmap
ret( rect
.width
, rect
.height
, 0 );
342 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
344 // The remaining still TODO
354 m_pixmap
= (WXPixmap
) 0;
357 // Construct a mask from a bitmap and a colour indicating
358 // the transparent area
359 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
361 m_pixmap
= (WXPixmap
) 0;
363 Create(bitmap
, colour
);
366 // Construct a mask from a bitmap and a palette index indicating
367 // the transparent area
368 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
370 m_pixmap
= (WXPixmap
) 0;
372 Create(bitmap
, paletteIndex
);
375 // Construct a mask from a mono bitmap (copies the bitmap).
376 wxMask::wxMask(const wxBitmap
& bitmap
)
378 m_pixmap
= (WXPixmap
) 0;
385 // TODO: this may be the wrong display
387 XFreePixmap ((Display
*) wxGetDisplay(), (Pixmap
) m_pixmap
);
390 // Create a mask from a mono bitmap (copies the bitmap).
391 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
))
397 // Create a mask from a bitmap and a palette index indicating
398 // the transparent area
399 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), int WXUNUSED(paletteIndex
))
405 // Create a mask from a bitmap and a colour indicating
406 // the transparent area
407 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), const wxColour
& WXUNUSED(colour
))
417 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
423 class WXDLLEXPORT wxXBMFileHandler
: public wxBitmapHandler
425 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler
)
427 inline wxXBMFileHandler()
431 m_type
= wxBITMAP_TYPE_XBM
;
434 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
435 int desiredWidth
, int desiredHeight
);
438 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler
, wxBitmapHandler
)
440 bool wxXBMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
,
441 long WXUNUSED(flags
),
442 int WXUNUSED(desiredWidth
),
443 int WXUNUSED(desiredHeight
))
445 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
446 if (!bitmap
->GetRefData())
447 bitmap
->SetRefData( new wxBitmapRefData() );
453 Display
*dpy
= (Display
*) wxGetDisplay();
454 M_BITMAPDATA
->m_display
= (WXDisplay
*) dpy
;
456 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
457 wxConstCast(name
.c_str(), char), &w
, &h
, &pixmap
, &hotX
, &hotY
);
458 M_BITMAPHANDLERDATA
->m_width
= w
;
459 M_BITMAPHANDLERDATA
->m_height
= h
;
460 M_BITMAPHANDLERDATA
->m_depth
= 1;
461 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
463 if ((value
== BitmapFileInvalid
) ||
464 (value
== BitmapOpenFailed
) ||
465 (value
== BitmapNoMemory
))
467 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
468 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) 0;
471 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
473 return M_BITMAPHANDLERDATA
->m_ok
;
476 class WXDLLEXPORT wxXBMDataHandler
: public wxBitmapHandler
478 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler
)
480 inline wxXBMDataHandler()
484 m_type
= wxBITMAP_TYPE_XBM_DATA
;
487 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
488 int width
, int height
, int depth
= 1);
490 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler
, wxBitmapHandler
)
492 bool wxXBMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
493 long WXUNUSED(flags
),
494 int width
, int height
, int WXUNUSED(depth
))
496 if (!bitmap
->GetRefData())
497 bitmap
->SetRefData( new wxBitmapRefData() );
499 M_BITMAPHANDLERDATA
->m_width
= width
;
500 M_BITMAPHANDLERDATA
->m_height
= height
;
501 M_BITMAPHANDLERDATA
->m_depth
= 1;
502 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
504 Display
*dpy
= (Display
*) wxGetDisplay();
505 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
507 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) XCreateBitmapFromData (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)), (char*) data
, width
, height
);
508 M_BITMAPHANDLERDATA
->m_ok
= (M_BITMAPHANDLERDATA
->m_pixmap
!= (WXPixmap
) 0) ;
511 // code for wxControl. TODO: can we avoid doing this until we need it?
512 // E.g. have CreateButtonPixmaps which is called on demand.
513 XImage
* image
= (XImage
*) XtMalloc (sizeof (XImage
));
514 image
->width
= width
;
515 image
->height
= height
;
516 image
->data
= (char*) data
;
519 image
->format
= XYBitmap
;
520 image
->byte_order
= LSBFirst
;
521 image
->bitmap_unit
= 8;
522 image
->bitmap_bit_order
= LSBFirst
;
523 image
->bitmap_pad
= 8;
524 image
->bytes_per_line
= (width
+ 7) >> 3;
527 sprintf (tmp
, "Im%x", (unsigned int) image
);
528 XmInstallImage (image
, tmp
);
530 // Build our manually stipped pixmap.
532 int bpl
= (width
+ 7) / 8;
533 char *data1
= new char[height
* bpl
];
534 char* bits
= (char*) data
;
536 for (i
= 0; i
< height
; i
++)
538 int mask
= i
% 2 ? 0x55 : 0xaa;
540 for (j
= 0; j
< bpl
; j
++)
541 data1
[i
* bpl
+ j
] = bits
[i
* bpl
+ j
] & mask
;
543 XImage
* insensImage
= (XImage
*) XtMalloc (sizeof (XImage
));
544 insensImage
->width
= width
;
545 insensImage
->height
= height
;
546 insensImage
->data
= data1
;
547 insensImage
->depth
= 1;
548 insensImage
->xoffset
= 0;
549 insensImage
->format
= XYBitmap
;
550 insensImage
->byte_order
= LSBFirst
;
551 insensImage
->bitmap_unit
= 8;
552 insensImage
->bitmap_bit_order
= LSBFirst
;
553 insensImage
->bitmap_pad
= 8;
554 insensImage
->bytes_per_line
= bpl
;
556 sprintf (tmp
, "Not%x", (unsigned int)insensImage
);
557 XmInstallImage (insensImage
, tmp
);
559 M_BITMAPHANDLERDATA
->m_image
= (WXImage
*) image
;
560 M_BITMAPHANDLERDATA
->m_insensImage
= (WXImage
*) insensImage
;
569 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
571 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
573 inline wxXPMFileHandler()
577 m_type
= wxBITMAP_TYPE_XPM
;
580 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
581 int desiredWidth
, int desiredHeight
);
582 virtual bool SaveFile(const wxBitmap
*bitmap
, const wxString
& name
,
583 wxBitmapType type
, const wxPalette
*palette
= NULL
);
586 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
588 bool wxXPMFileHandler::LoadFile( wxBitmap
*bitmap
, const wxString
& name
,
589 long WXUNUSED(flags
),
590 int WXUNUSED(desiredWidth
),
591 int WXUNUSED(desiredHeight
) )
593 if (!bitmap
->GetRefData())
594 bitmap
->SetRefData( new wxBitmapRefData() );
596 Display
*dpy
= (Display
*) wxGetDisplay();
597 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
599 XpmAttributes xpmAttr
;
603 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
604 xpmAttr
.valuemask
= XpmReturnInfos
| XpmCloseness
;
605 xpmAttr
.closeness
= 40000;
606 int errorStatus
= XpmReadFileToPixmap(dpy
,
607 RootWindow(dpy
, DefaultScreen(dpy
)),
608 wxConstCast(name
.c_str(), char),
609 &pixmap
, &mask
, &xpmAttr
);
611 if (errorStatus
== XpmSuccess
)
613 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
616 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
617 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
620 unsigned int depthRet
;
622 unsigned int widthRet
, heightRet
, borderWidthRet
;
623 Window rootWindowRet
;
624 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
625 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
627 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
628 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
631 if ( xpmAttr.npixels > 2 )
633 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
636 M_BITMAPHANDLERDATA->m_depth = 1; // mono
640 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
642 // M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
644 XpmFreeAttributes(&xpmAttr
);
646 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
650 // XpmDebugError(errorStatus, name);
651 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
656 bool wxXPMFileHandler::SaveFile( const wxBitmap
*bitmap
, const wxString
& name
,
657 wxBitmapType
WXUNUSED(type
),
658 const wxPalette
*WXUNUSED(palette
))
660 if (M_BITMAPHANDLERDATA
->m_ok
&& M_BITMAPHANDLERDATA
->m_pixmap
)
662 Display
*dpy
= (Display
*) M_BITMAPHANDLERDATA
->m_display
;
663 int errorStatus
= XpmWriteFileFromPixmap(dpy
,
664 wxConstCast(name
.c_str(), char),
665 (Pixmap
) M_BITMAPHANDLERDATA
->m_pixmap
,
666 (M_BITMAPHANDLERDATA
->m_bitmapMask
? (Pixmap
) M_BITMAPHANDLERDATA
->m_bitmapMask
->GetPixmap() : (Pixmap
) 0),
667 (XpmAttributes
*) NULL
);
668 if (errorStatus
== XpmSuccess
)
677 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
679 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
681 inline wxXPMDataHandler()
685 m_type
= wxBITMAP_TYPE_XPM_DATA
;
688 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
689 int width
, int height
, int depth
= 1);
691 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
693 bool wxXPMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
694 long WXUNUSED(flags
),
695 int width
, int height
, int WXUNUSED(depth
))
697 if (!bitmap
->GetRefData())
698 bitmap
->SetRefData( new wxBitmapRefData() );
700 M_BITMAPHANDLERDATA
->m_width
= width
;
701 M_BITMAPHANDLERDATA
->m_height
= height
;
702 M_BITMAPHANDLERDATA
->m_depth
= 1;
703 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
705 Display
*dpy
= (Display
*) wxGetDisplay();
706 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
708 XpmAttributes xpmAttr
;
710 xpmAttr
.valuemask
= XpmReturnInfos
; /* nothing yet, but get infos back */
713 XpmColorSymbol symbolicColors
[4];
714 if (sg_Control
&& sg_Control
->GetMainWidget())
716 symbolicColors
[0].name
= "foreground";
717 symbolicColors
[0].value
= NULL
;
718 symbolicColors
[1].name
= "background";
719 symbolicColors
[1].value
= NULL
;
720 XtVaGetValues((Widget
) sg_Control
->GetMainWidget(),
721 XmNforeground
, &symbolicColors
[0].pixel
,
722 XmNbackground
, &symbolicColors
[1].pixel
,NULL
);
723 xpmAttr
.numsymbols
= 2;
724 xpmAttr
.colorsymbols
= symbolicColors
;
725 xpmAttr
.valuemask
|= XpmColorSymbols
; // add flag
731 int ErrorStatus
= XpmCreatePixmapFromData(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)),
732 (char**) data
, &pixmap
, &mask
, &xpmAttr
);
733 if (ErrorStatus
== XpmSuccess
)
736 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
737 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
739 unsigned int depthRet
;
741 unsigned int widthRet
, heightRet
, borderWidthRet
;
742 Window rootWindowRet
;
743 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
744 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
747 if ( xpmAttr.npixels > 2 )
749 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
752 M_BITMAPHANDLERDATA->m_depth = 1; // mono
756 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
758 // M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
759 XpmFreeAttributes(&xpmAttr
);
760 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
761 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
764 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
765 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
770 // XpmDebugError(ErrorStatus, NULL);
771 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
773 return M_BITMAPHANDLERDATA
->m_ok
;
776 #endif // wxHAVE_LIB_XPM
778 void wxBitmap::InitStandardHandlers()
780 // Initialize all standard bitmap or derived class handlers here.
781 AddHandler(new wxXBMFileHandler
);
782 AddHandler(new wxXBMDataHandler
);
784 // XPM is considered standard for Motif, although it can be omitted if
785 // libXpm is not installed
787 AddHandler(new wxXPMFileHandler
);
788 AddHandler(new wxXPMDataHandler
);
789 #endif // wxHAVE_LIB_XPM
793 WXPixmap
wxBitmap::GetLabelPixmap (WXWidget w
)
796 return (WXPixmap
)NULL
;
797 // if (M_BITMAPDATA->m_image == (WXPixmap) 0)
798 return M_BITMAPDATA
->m_pixmap
;
801 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
806 if (labelPixmap) return labelPixmap;
807 things can be wrong, because colors can have been changed.
811 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
812 we got BadDrawable if the pixmap is referenced by multiples widgets
816 So, before doing thing really clean, I just do nothing; if the pixmap is
817 referenced by many widgets, Motif performs caching functions.
818 And if pixmap is referenced with multiples colors, we just have some
819 memory leaks... I hope we can deal with them...
821 // Must be destroyed, because colours can have been changed!
822 if (M_BITMAPDATA
->m_labelPixmap
)
823 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_labelPixmap
);
827 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
830 Widget widget
= (Widget
) w
;
832 while (XmIsGadget ( widget
))
833 widget
= XtParent (widget
);
834 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
836 M_BITMAPDATA
->m_labelPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
838 return M_BITMAPDATA
->m_labelPixmap
;
842 WXPixmap
wxBitmap::GetArmPixmap (WXWidget w
)
844 // if (M_BITMAPDATA->m_image == (WXPixmap) 0)
845 return M_BITMAPDATA
->m_pixmap
;
848 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
850 // See GetLabelPixmap () comment
852 // Must be destroyed, because colours can have been changed!
853 if (M_BITMAPDATA
->m_armPixmap
)
854 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_armPixmap
);
858 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
861 Widget widget
= (Widget
) w
;
863 XtVaGetValues (widget
, XmNarmColor
, &bg
, NULL
);
864 while (XmIsGadget (widget
))
865 widget
= XtParent (widget
);
866 XtVaGetValues (widget
, XmNforeground
, &fg
, NULL
);
868 M_BITMAPDATA
->m_armPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
870 return M_BITMAPDATA
->m_armPixmap
;
874 WXPixmap
wxBitmap::GetInsensPixmap (WXWidget w
)
876 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
879 return (WXPixmap
)NULL
;
880 if (M_BITMAPDATA
->m_insensPixmap
)
881 return M_BITMAPDATA
->m_insensPixmap
;
885 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XCreateInsensitivePixmap(dpy
, (Pixmap
) M_BITMAPDATA
->m_pixmap
);
886 if (M_BITMAPDATA
->m_insensPixmap
)
887 return M_BITMAPDATA
->m_insensPixmap
;
889 return M_BITMAPDATA
->m_pixmap
;
892 // if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
893 return M_BITMAPDATA
->m_pixmap
;
897 See
GetLabelPixmap () comment
898 // Must be destroyed, because colours can have been changed!
899 if (M_BITMAPDATA
->m_insensPixmap
)
900 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), (Pixmap
) M_BITMAPDATA
->m_insensPixmap
);
904 sprintf (tmp
, "Not%x", (unsigned int) M_BITMAPDATA
->m_insensImage
);
907 Widget widget
= (Widget
) w
;
909 while (XmIsGadget (widget
))
910 widget
= XtParent (widget
);
911 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
913 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
915 return M_BITMAPDATA
->m_insensPixmap
;
920 // Creates a bitmap with transparent areas drawn in
922 wxBitmap
wxCreateMaskedBitmap(const wxBitmap
& bitmap
, wxColour
& colour
)
924 wxBitmap
newBitmap(bitmap
.GetWidth(),
929 srcDC
.SelectObject(bitmap
);
930 destDC
.SelectObject(newBitmap
);
932 wxBrush
brush(colour
, wxSOLID
);
933 destDC
.SetOptimization(FALSE
);
934 destDC
.SetBackground(brush
);
936 destDC
.Blit(0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), & srcDC
, 0, 0, wxCOPY
, TRUE
);
944 //-----------------------------------------------------------------------------
945 // wxImage conversion routines
946 //-----------------------------------------------------------------------------
950 Date: Wed, 05 Jan 2000 11:45:40 +0100
951 From: Frits Boel <boel@niob.knaw.nl>
952 To: julian.smart@ukonline.co.uk
953 Subject: Patch for Motif ConvertToBitmap
957 I've been working on a wxWin application for image processing. From the
958 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
959 till I looked in the source code of image.cpp. I saw that converting a
960 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
961 to the 256 colors of the palet. A very time-consuming piece of code!
963 Because I wanted a faster application, I've made a 'patch' for this. In
964 short: every pixel of the image is compared to a sorted list with
965 colors. If the color is found in the list, the palette entry is
966 returned; if the color is not found, the color palette is searched and
967 then the palette entry is returned and the color added to the sorted
970 Maybe there is another method for this, namely changing the palette
971 itself (if the colors are known, as is the case with tiffs with a
972 colormap). I did not look at this, maybe someone else did?
974 The code of the patch is attached, have a look on it, and maybe you will
975 ship it with the next release of wxMotif?
980 Software engineer at Hubrecht Laboratory, The Netherlands.
987 wxSearchColor( void );
988 wxSearchColor( int size
, XColor
*colors
);
989 ~wxSearchColor( void );
991 int SearchColor( int r
, int g
, int b
);
993 int AddColor( unsigned int value
, int pos
);
1004 wxSearchColor::wxSearchColor( void )
1007 colors
= (XColor
*) NULL
;
1008 color
= (unsigned int *) NULL
;
1009 entry
= (int*) NULL
;
1015 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
1020 color
= new unsigned int[size
];
1021 entry
= new int [size
];
1023 for (i
= 0; i
< size
; i
++ ) {
1027 bottom
= top
= ( size
>> 1 );
1030 wxSearchColor::~wxSearchColor( void )
1032 if ( color
) delete[] color
;
1033 if ( entry
) delete[] entry
;
1036 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1038 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1043 while ( begin
<= end
) {
1045 middle
= ( begin
+ end
) >> 1;
1047 if ( value
== color
[middle
] ) {
1048 return( entry
[middle
] );
1049 } else if ( value
< color
[middle
] ) {
1057 return AddColor( value
, middle
);
1060 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1064 int max
= 3 * (65536);
1065 for ( i
= 0; i
< 256; i
++ ) {
1066 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1067 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1068 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1069 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1070 if (sum
< max
) { pixel
= i
; max
= sum
; }
1073 if ( entry
[pos
] < 0 ) {
1076 } else if ( value
< color
[pos
] ) {
1079 for ( i
= bottom
; i
< pos
; i
++ ) {
1080 color
[i
-1] = color
[i
];
1081 entry
[i
-1] = entry
[i
];
1084 color
[pos
-1] = value
;
1085 entry
[pos
-1] = pixel
;
1086 } else if ( top
< size
-1 ) {
1087 for ( i
= top
; i
>= pos
; i
-- ) {
1088 color
[i
+1] = color
[i
];
1089 entry
[i
+1] = entry
[i
];
1098 if ( top
< size
-1 ) {
1099 for ( i
= top
; i
> pos
; i
-- ) {
1100 color
[i
+1] = color
[i
];
1101 entry
[i
+1] = entry
[i
];
1104 color
[pos
+1] = value
;
1105 entry
[pos
+1] = pixel
;
1106 } else if ( bottom
> 0 ) {
1107 for ( i
= bottom
; i
< pos
; i
++ ) {
1108 color
[i
-1] = color
[i
];
1109 entry
[i
-1] = entry
[i
];
1122 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
1124 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
1125 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
1127 m_refData
= new wxBitmapRefData();
1129 int width
= image
.GetWidth();
1130 int height
= image
.GetHeight();
1132 SetHeight( height
);
1135 Display
*dpy
= (Display
*) wxGetDisplay();
1136 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1137 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1141 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1142 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1144 Create( width
, height
, bpp
);
1148 XImage
*mask_image
= (XImage
*) NULL
;
1149 if (image
.HasMask())
1151 mask_image
= XCreateImage( dpy
, vis
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1152 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
1155 // Retrieve depth info
1157 XVisualInfo vinfo_template
;
1160 vinfo_template
.visual
= vis
;
1161 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1162 vinfo_template
.depth
= bpp
;
1165 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
,
1166 &vinfo_template
, &nitem
);
1168 wxCHECK_MSG( vi
, FALSE
, wxT("no visual") );
1170 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1171 if (bpp
< 8) bpp
= 8;
1175 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1176 byte_order b_o
= RGB
;
1180 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1181 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1182 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1183 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1184 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1185 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1190 int r_mask
= image
.GetMaskRed();
1191 int g_mask
= image
.GetMaskGreen();
1192 int b_mask
= image
.GetMaskBlue();
1197 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1199 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1200 XQueryColors( dpy
, cmap
, colors
, 256 );
1203 wxSearchColor
scolor( 256, colors
);
1204 unsigned char* data
= image
.GetData();
1206 bool hasMask
= image
.HasMask();
1209 for (int y
= 0; y
< height
; y
++)
1211 for (int x
= 0; x
< width
; x
++)
1213 int r
= data
[index
];
1215 int g
= data
[index
];
1217 int b
= data
[index
];
1222 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1223 XPutPixel( mask_image
, x
, y
, 0 );
1225 XPutPixel( mask_image
, x
, y
, 1 );
1232 #if 0 // Old, slower code
1235 if (wxTheApp->m_colorCube)
1237 pixel = wxTheApp->m_colorCube
1238 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1243 int max
= 3 * (65536);
1244 for (int i
= 0; i
< 256; i
++)
1246 int rdiff
= (r
<< 8) - colors
[i
].red
;
1247 int gdiff
= (g
<< 8) - colors
[i
].green
;
1248 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1249 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1250 if (sum
< max
) { pixel
= i
; max
= sum
; }
1257 // And this is all to get the 'right' color...
1258 int pixel
= scolor
.SearchColor( r
, g
, b
);
1259 XPutPixel( data_image
, x
, y
, pixel
);
1264 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1265 XPutPixel( data_image
, x
, y
, pixel
);
1270 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1271 XPutPixel( data_image
, x
, y
, pixel
);
1280 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1281 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1282 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1283 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1284 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1285 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1287 XPutPixel( data_image
, x
, y
, pixel
);
1297 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1298 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1299 XPutImage( dpy
, (Drawable
)GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1301 XDestroyImage( data_image
);
1305 if (image
.HasMask())
1307 wxBitmap
maskBitmap(width
, height
, 1);
1309 GC gcMask
= XCreateGC( dpy
, (Pixmap
) maskBitmap
.GetPixmap(), (XtGCMask
) 0, (XGCValues
*)NULL
);
1310 XPutImage( dpy
, (Drawable
)maskBitmap
.GetPixmap(), gcMask
, mask_image
, 0, 0, 0, 0, width
, height
);
1312 XDestroyImage( mask_image
);
1313 XFreeGC( dpy
, gcMask
);
1315 wxMask
* mask
= new wxMask
;
1316 mask
->SetPixmap(maskBitmap
.GetPixmap());
1320 maskBitmap
.SetPixmapNull();
1327 wxImage
wxBitmap::ConvertToImage() const
1331 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
1333 Display
*dpy
= (Display
*) wxGetDisplay();
1334 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1335 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1337 XImage
*ximage
= XGetImage( dpy
,
1338 (Drawable
)GetPixmap(),
1340 GetWidth(), GetHeight(),
1341 AllPlanes
, ZPixmap
);
1343 wxCHECK_MSG( ximage
, wxNullImage
, wxT("couldn't create image") );
1345 image
.Create( GetWidth(), GetHeight() );
1346 char unsigned *data
= image
.GetData();
1350 XDestroyImage( ximage
);
1351 wxFAIL_MSG( wxT("couldn't create image") );
1356 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1359 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1361 GetWidth(), GetHeight() );
1363 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1367 // Retrieve depth info
1369 XVisualInfo vinfo_template
;
1372 vinfo_template
.visual
= vis
;
1373 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1374 vinfo_template
.depth
= bpp
;
1377 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1379 wxCHECK_MSG( vi
, wxNullImage
, wxT("no visual") );
1381 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1388 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1390 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1391 XQueryColors( dpy
, cmap
, colors
, 256 );
1395 for (int j
= 0; j
< GetHeight(); j
++)
1397 for (int i
= 0; i
< GetWidth(); i
++)
1399 int pixel
= XGetPixel( ximage
, i
, j
);
1402 data
[pos
] = colors
[pixel
].red
>> 8;
1403 data
[pos
+1] = colors
[pixel
].green
>> 8;
1404 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1405 } else if (bpp
== 15)
1407 data
[pos
] = (pixel
>> 7) & 0xf8;
1408 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1409 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1410 } else if (bpp
== 16)
1412 data
[pos
] = (pixel
>> 8) & 0xf8;
1413 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1414 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1417 data
[pos
] = (pixel
>> 16) & 0xff;
1418 data
[pos
+1] = (pixel
>> 8) & 0xff;
1419 data
[pos
+2] = pixel
& 0xff;
1425 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1426 if (mask_pixel == 0)
1439 XDestroyImage( ximage
);
1441 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );