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/control.h"
27 #include "wx/dcmemory.h"
32 #pragma message disable nosimpint
36 #pragma message enable nosimpint
39 #include "wx/motif/private.h"
47 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
48 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
50 wxBitmapRefData::wxBitmapRefData()
60 m_pixmap
= (WXPixmap
) 0;
61 m_display
= (WXDisplay
*) 0;
63 m_freePixmap
= TRUE
; //TODO: necessary?
64 m_freeColors
= (unsigned long*) 0;
65 m_freeColorsCount
= 0;
67 // These 5 variables are for wxControl
68 m_insensPixmap
= (WXPixmap
) 0;
69 m_labelPixmap
= (WXPixmap
) 0;
70 m_armPixmap
= (WXPixmap
) 0;
71 m_image
= (WXImage
*) 0;
72 m_insensImage
= (WXImage
*) 0;
75 wxBitmapRefData::~wxBitmapRefData()
78 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_labelPixmap
);
81 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_armPixmap
);
84 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_insensPixmap
);
88 XmUninstallImage ((XImage
*) m_image
);
89 XtFree ((char *) (XImage
*) m_image
);
94 XmUninstallImage ((XImage
*) m_insensImage
);
95 delete[] ((XImage
*) m_insensImage
)->data
;
96 XtFree ((char *) (XImage
*) m_insensImage
);
98 if (m_pixmap
&& m_freePixmap
)
99 XFreePixmap ((Display
*) m_display
, (Pixmap
) m_pixmap
);
103 int screen
= DefaultScreen((Display
*) m_display
);
104 Colormap cmp
= DefaultColormap((Display
*) m_display
,screen
);
106 for(llp
= 0;llp
< m_freeColorsCount
;llp
++)
107 XFreeColors((Display
*) m_display
, cmp
, &m_freeColors
[llp
], 1, 0L);
116 wxList
wxBitmap::sm_handlers
;
118 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
125 wxBitmap::~wxBitmap()
129 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
131 m_refData
= new wxBitmapRefData
;
133 (void) Create((void*) bits
, wxBITMAP_TYPE_XBM_DATA
, width
, height
, depth
);
136 wxBitmap::wxBitmap(int w
, int h
, int d
)
138 (void)Create(w
, h
, d
);
141 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
)
143 (void) Create(data
, type
, width
, height
, depth
);
146 wxBitmap::wxBitmap(const wxString
& filename
, long type
)
148 LoadFile(filename
, (int)type
);
151 // Create from XPM data
152 static wxControl
* sg_Control
= NULL
;
153 wxBitmap::wxBitmap(char **data
, wxControl
* control
)
155 // Pass the control to the Create function using a global
156 sg_Control
= control
;
158 (void) Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
160 sg_Control
= (wxControl
*) NULL
;
163 bool wxBitmap::CreateFromXpm(const char **bits
)
165 wxCHECK_MSG( bits
, FALSE
, _T("NULL pointer in wxBitmap::CreateFromXpm") );
167 return Create(bits
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
170 bool wxBitmap::Create(int w
, int h
, int d
)
174 m_refData
= new wxBitmapRefData
;
177 d
= wxDisplayDepth();
179 M_BITMAPDATA
->m_width
= w
;
180 M_BITMAPDATA
->m_height
= h
;
181 M_BITMAPDATA
->m_depth
= d
;
182 M_BITMAPDATA
->m_freePixmap
= TRUE
;
184 Display
*dpy
= (Display
*) wxGetDisplay();
186 M_BITMAPDATA
->m_display
= dpy
; /* MATTHEW: [4] Remember the display */
188 M_BITMAPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
191 M_BITMAPDATA
->m_ok
= (M_BITMAPDATA
->m_pixmap
!= (WXPixmap
) 0) ;
192 return M_BITMAPDATA
->m_ok
;
195 bool wxBitmap::LoadFile(const wxString
& filename
, long type
)
199 m_refData
= new wxBitmapRefData
;
201 wxBitmapHandler
*handler
= FindHandler(type
);
203 if ( handler
== NULL
) {
205 if (!image
.LoadFile( filename
, type
)) return FALSE
;
208 *this = image
.ConvertToBitmap();
214 return handler
->LoadFile(this, filename
, type
, -1, -1);
217 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
)
221 m_refData
= new wxBitmapRefData
;
223 wxBitmapHandler
*handler
= FindHandler(type
);
225 if ( handler
== NULL
) {
226 wxLogWarning("no data bitmap handler for type %d defined.", type
);
231 return handler
->Create(this, data
, type
, width
, height
, depth
);
234 bool wxBitmap::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
236 wxBitmapHandler
*handler
= FindHandler(type
);
238 if ( handler
== NULL
) { // try wxImage
239 wxImage
image( *this );
240 if (image
.Ok()) return image
.SaveFile( filename
, type
);
244 return handler
->SaveFile(this, filename
, type
, palette
);
247 void wxBitmap::SetWidth(int w
)
250 m_refData
= new wxBitmapRefData
;
252 M_BITMAPDATA
->m_width
= w
;
255 void wxBitmap::SetHeight(int h
)
258 m_refData
= new wxBitmapRefData
;
260 M_BITMAPDATA
->m_height
= h
;
263 void wxBitmap::SetDepth(int d
)
266 m_refData
= new wxBitmapRefData
;
268 M_BITMAPDATA
->m_depth
= d
;
271 void wxBitmap::SetQuality(int q
)
274 m_refData
= new wxBitmapRefData
;
276 M_BITMAPDATA
->m_quality
= q
;
279 void wxBitmap::SetOk(bool isOk
)
282 m_refData
= new wxBitmapRefData
;
284 M_BITMAPDATA
->m_ok
= isOk
;
287 void wxBitmap::SetPalette(const wxPalette
& palette
)
290 m_refData
= new wxBitmapRefData
;
292 M_BITMAPDATA
->m_bitmapPalette
= palette
;
295 void wxBitmap::SetMask(wxMask
*mask
)
298 m_refData
= new wxBitmapRefData
;
300 M_BITMAPDATA
->m_bitmapMask
= mask
;
303 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
306 (rect
.x
>= 0) && (rect
.y
>= 0) &&
307 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) && (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
308 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
310 wxBitmap
ret( rect
.width
, rect
.height
, 0 );
311 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
313 // The remaining still TODO
317 void wxBitmap::AddHandler(wxBitmapHandler
*handler
)
319 sm_handlers
.Append(handler
);
322 void wxBitmap::InsertHandler(wxBitmapHandler
*handler
)
324 sm_handlers
.Insert(handler
);
327 bool wxBitmap::RemoveHandler(const wxString
& name
)
329 wxBitmapHandler
*handler
= FindHandler(name
);
332 sm_handlers
.DeleteObject(handler
);
339 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& name
)
341 wxNode
*node
= sm_handlers
.First();
344 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
345 if ( handler
->GetName() == name
)
352 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& extension
, long bitmapType
)
354 wxNode
*node
= sm_handlers
.First();
357 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
358 if ( handler
->GetExtension() == extension
&&
359 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
366 wxBitmapHandler
*wxBitmap::FindHandler(long bitmapType
)
368 wxNode
*node
= sm_handlers
.First();
371 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
372 if (handler
->GetType() == bitmapType
)
385 m_pixmap
= (WXPixmap
) 0;
388 // Construct a mask from a bitmap and a colour indicating
389 // the transparent area
390 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
392 m_pixmap
= (WXPixmap
) 0;
394 Create(bitmap
, colour
);
397 // Construct a mask from a bitmap and a palette index indicating
398 // the transparent area
399 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
401 m_pixmap
= (WXPixmap
) 0;
403 Create(bitmap
, paletteIndex
);
406 // Construct a mask from a mono bitmap (copies the bitmap).
407 wxMask::wxMask(const wxBitmap
& bitmap
)
409 m_pixmap
= (WXPixmap
) 0;
416 // TODO: this may be the wrong display
418 XFreePixmap ((Display
*) wxGetDisplay(), (Pixmap
) m_pixmap
);
421 // Create a mask from a mono bitmap (copies the bitmap).
422 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
))
428 // Create a mask from a bitmap and a palette index indicating
429 // the transparent area
430 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), int WXUNUSED(paletteIndex
))
436 // Create a mask from a bitmap and a colour indicating
437 // the transparent area
438 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), const wxColour
& WXUNUSED(colour
))
448 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
450 bool wxBitmapHandler::Create(wxBitmap
*WXUNUSED(bitmap
), void *WXUNUSED(data
), long WXUNUSED(type
),
451 int WXUNUSED(width
), int WXUNUSED(height
), int WXUNUSED(depth
))
456 bool wxBitmapHandler::LoadFile(wxBitmap
*WXUNUSED(bitmap
), const wxString
& WXUNUSED(name
), long WXUNUSED(type
),
457 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
462 bool wxBitmapHandler::SaveFile(wxBitmap
*WXUNUSED(bitmap
), const wxString
& WXUNUSED(name
), int WXUNUSED(type
),
463 const wxPalette
*WXUNUSED(palette
))
472 class WXDLLEXPORT wxXBMFileHandler
: public wxBitmapHandler
474 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler
)
476 inline wxXBMFileHandler()
480 m_type
= wxBITMAP_TYPE_XBM
;
483 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
484 int desiredWidth
, int desiredHeight
);
486 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler
, wxBitmapHandler
)
488 bool wxXBMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long WXUNUSED(flags
),
489 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
491 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
497 Display
*dpy
= (Display
*) wxGetDisplay();
498 M_BITMAPDATA
->m_display
= (WXDisplay
*) dpy
;
500 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
501 (char*) (const char*) name
, &w
, &h
, &pixmap
, &hotX
, &hotY
);
502 M_BITMAPHANDLERDATA
->m_width
= w
;
503 M_BITMAPHANDLERDATA
->m_height
= h
;
504 M_BITMAPHANDLERDATA
->m_depth
= 1;
505 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
507 if ((value
== BitmapFileInvalid
) ||
508 (value
== BitmapOpenFailed
) ||
509 (value
== BitmapNoMemory
))
511 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
512 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) 0;
515 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
517 return M_BITMAPHANDLERDATA
->m_ok
;
520 class WXDLLEXPORT wxXBMDataHandler
: public wxBitmapHandler
522 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler
)
524 inline wxXBMDataHandler()
528 m_type
= wxBITMAP_TYPE_XBM_DATA
;
531 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
, int width
, int height
, int depth
= 1);
533 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler
, wxBitmapHandler
)
535 bool wxXBMDataHandler::Create( wxBitmap
*bitmap
, void *data
, long WXUNUSED(flags
),
536 int width
, int height
, int WXUNUSED(depth
))
538 M_BITMAPHANDLERDATA
->m_width
= width
;
539 M_BITMAPHANDLERDATA
->m_height
= height
;
540 M_BITMAPHANDLERDATA
->m_depth
= 1;
541 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
543 Display
*dpy
= (Display
*) wxGetDisplay();
544 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
546 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) XCreateBitmapFromData (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)), (char*) data
, width
, height
);
547 M_BITMAPHANDLERDATA
->m_ok
= (M_BITMAPHANDLERDATA
->m_pixmap
!= (WXPixmap
) 0) ;
549 // code for wxControl. TODO: can we avoid doing this until we need it?
550 // E.g. have CreateButtonPixmaps which is called on demand.
551 XImage
* image
= (XImage
*) XtMalloc (sizeof (XImage
));
552 image
->width
= width
;
553 image
->height
= height
;
554 image
->data
= (char*) data
;
557 image
->format
= XYBitmap
;
558 image
->byte_order
= LSBFirst
;
559 image
->bitmap_unit
= 8;
560 image
->bitmap_bit_order
= LSBFirst
;
561 image
->bitmap_pad
= 8;
562 image
->bytes_per_line
= (width
+ 7) >> 3;
565 sprintf (tmp
, "Im%x", (unsigned int) image
);
566 XmInstallImage (image
, tmp
);
568 // Build our manually stipped pixmap.
570 int bpl
= (width
+ 7) / 8;
571 char *data1
= new char[height
* bpl
];
572 char* bits
= (char*) data
;
574 for (i
= 0; i
< height
; i
++)
576 int mask
= i
% 2 ? 0x55 : 0xaa;
578 for (j
= 0; j
< bpl
; j
++)
579 data1
[i
* bpl
+ j
] = bits
[i
* bpl
+ j
] & mask
;
581 XImage
* insensImage
= (XImage
*) XtMalloc (sizeof (XImage
));
582 insensImage
->width
= width
;
583 insensImage
->height
= height
;
584 insensImage
->data
= data1
;
585 insensImage
->depth
= 1;
586 insensImage
->xoffset
= 0;
587 insensImage
->format
= XYBitmap
;
588 insensImage
->byte_order
= LSBFirst
;
589 insensImage
->bitmap_unit
= 8;
590 insensImage
->bitmap_bit_order
= LSBFirst
;
591 insensImage
->bitmap_pad
= 8;
592 insensImage
->bytes_per_line
= bpl
;
594 sprintf (tmp
, "Not%x", (unsigned int)insensImage
);
595 XmInstallImage (insensImage
, tmp
);
597 M_BITMAPHANDLERDATA
->m_image
= (WXImage
*) image
;
598 M_BITMAPHANDLERDATA
->m_insensImage
= (WXImage
*) insensImage
;
604 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
606 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
608 inline wxXPMFileHandler()
612 m_type
= wxBITMAP_TYPE_XPM
;
615 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
616 int desiredWidth
, int desiredHeight
);
617 virtual bool SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*palette
= NULL
);
620 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
622 bool wxXPMFileHandler::LoadFile( wxBitmap
*bitmap
, const wxString
& name
, long WXUNUSED(flags
),
623 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
) )
625 Display
*dpy
= (Display
*) wxGetDisplay();
626 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
628 XpmAttributes xpmAttr
;
632 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
633 xpmAttr
.valuemask
= XpmReturnInfos
| XpmCloseness
;
634 xpmAttr
.closeness
= 40000;
635 int errorStatus
= XpmReadFileToPixmap(dpy
,
636 RootWindow(dpy
, DefaultScreen(dpy
)), (char*) (const char*) name
,
637 &pixmap
, &mask
, &xpmAttr
);
639 if (errorStatus
== XpmSuccess
)
641 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
644 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
645 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
648 unsigned int depthRet
;
650 unsigned int widthRet
, heightRet
, borderWidthRet
;
651 Window rootWindowRet
;
652 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
653 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
655 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
656 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
659 if ( xpmAttr.npixels > 2 )
661 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
664 M_BITMAPHANDLERDATA->m_depth = 1; // mono
668 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
670 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
672 XpmFreeAttributes(&xpmAttr
);
674 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
678 // XpmDebugError(errorStatus, name);
679 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
684 bool wxXPMFileHandler::SaveFile( wxBitmap
*bitmap
, const wxString
& name
, int WXUNUSED(type
),
685 const wxPalette
*WXUNUSED(palette
))
687 if (M_BITMAPHANDLERDATA
->m_ok
&& M_BITMAPHANDLERDATA
->m_pixmap
)
689 Display
*dpy
= (Display
*) M_BITMAPHANDLERDATA
->m_display
;
690 int errorStatus
= XpmWriteFileFromPixmap(dpy
, (char*) (const char*) name
,
691 (Pixmap
) M_BITMAPHANDLERDATA
->m_pixmap
,
692 (M_BITMAPHANDLERDATA
->m_bitmapMask
? (Pixmap
) M_BITMAPHANDLERDATA
->m_bitmapMask
->GetPixmap() : (Pixmap
) 0),
693 (XpmAttributes
*) NULL
);
694 if (errorStatus
== XpmSuccess
)
703 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
705 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
707 inline wxXPMDataHandler()
711 m_type
= wxBITMAP_TYPE_XPM_DATA
;
714 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
, int width
, int height
, int depth
= 1);
716 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
718 bool wxXPMDataHandler::Create( wxBitmap
*bitmap
, void *data
, long WXUNUSED(flags
),
719 int width
, int height
, int WXUNUSED(depth
))
721 M_BITMAPHANDLERDATA
->m_width
= width
;
722 M_BITMAPHANDLERDATA
->m_height
= height
;
723 M_BITMAPHANDLERDATA
->m_depth
= 1;
724 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
726 Display
*dpy
= (Display
*) wxGetDisplay();
727 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
729 XpmAttributes xpmAttr
;
731 xpmAttr
.valuemask
= XpmReturnInfos
; /* nothing yet, but get infos back */
733 XpmColorSymbol symbolicColors
[4];
734 if (sg_Control
&& sg_Control
->GetMainWidget())
736 symbolicColors
[0].name
= "foreground";
737 symbolicColors
[0].value
= NULL
;
738 symbolicColors
[1].name
= "background";
739 symbolicColors
[1].value
= NULL
;
740 XtVaGetValues((Widget
) sg_Control
->GetMainWidget(),
741 XmNforeground
, &symbolicColors
[0].pixel
,
742 XmNbackground
, &symbolicColors
[1].pixel
,NULL
);
743 xpmAttr
.numsymbols
= 2;
744 xpmAttr
.colorsymbols
= symbolicColors
;
745 xpmAttr
.valuemask
|= XpmColorSymbols
; // add flag
750 int ErrorStatus
= XpmCreatePixmapFromData(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)),
751 (char**) data
, &pixmap
, &mask
, &xpmAttr
);
752 if (ErrorStatus
== XpmSuccess
)
755 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
756 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
758 unsigned int depthRet
;
760 unsigned int widthRet
, heightRet
, borderWidthRet
;
761 Window rootWindowRet
;
762 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
763 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
766 if ( xpmAttr.npixels > 2 )
768 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
771 M_BITMAPHANDLERDATA->m_depth = 1; // mono
775 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
777 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
778 XpmFreeAttributes(&xpmAttr
);
779 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
780 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
783 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
784 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
789 // XpmDebugError(ErrorStatus, NULL);
790 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
792 return M_BITMAPHANDLERDATA
->m_ok
;
795 #endif // wxHAVE_LIB_XPM
797 void wxBitmap::CleanUpHandlers()
799 wxNode
*node
= sm_handlers
.First();
802 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
803 wxNode
*next
= node
->Next();
810 void wxBitmap::InitStandardHandlers()
812 // Initialize all standard bitmap or derived class handlers here.
813 AddHandler(new wxXBMFileHandler
);
814 AddHandler(new wxXBMDataHandler
);
816 // XPM is considered standard for Motif, although it can be omitted if
817 // libXpm is not installed
819 AddHandler(new wxXPMFileHandler
);
820 AddHandler(new wxXPMDataHandler
);
821 #endif // wxHAVE_LIB_XPM
824 WXPixmap
wxBitmap::GetLabelPixmap (WXWidget w
)
826 if (M_BITMAPDATA
->m_image
== (WXPixmap
) 0)
827 return M_BITMAPDATA
->m_pixmap
;
829 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
834 if (labelPixmap) return labelPixmap;
835 things can be wrong, because colors can have been changed.
839 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
840 we got BadDrawable if the pixmap is referenced by multiples widgets
844 So, before doing thing really clean, I just do nothing; if the pixmap is
845 referenced by many widgets, Motif performs caching functions.
846 And if pixmap is referenced with multiples colors, we just have some
847 memory leaks... I hope we can deal with them...
849 // Must be destroyed, because colours can have been changed!
850 if (M_BITMAPDATA
->m_labelPixmap
)
851 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_labelPixmap
);
855 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
858 Widget widget
= (Widget
) w
;
860 while (XmIsGadget ( widget
))
861 widget
= XtParent (widget
);
862 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
864 M_BITMAPDATA
->m_labelPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
866 return M_BITMAPDATA
->m_labelPixmap
;
869 WXPixmap
wxBitmap::GetArmPixmap (WXWidget w
)
871 if (M_BITMAPDATA
->m_image
== (WXPixmap
) 0)
872 return M_BITMAPDATA
->m_pixmap
;
874 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
876 // See GetLabelPixmap () comment
878 // Must be destroyed, because colours can have been changed!
879 if (M_BITMAPDATA
->m_armPixmap
)
880 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_armPixmap
);
884 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
887 Widget widget
= (Widget
) w
;
889 XtVaGetValues (widget
, XmNarmColor
, &bg
, NULL
);
890 while (XmIsGadget (widget
))
891 widget
= XtParent (widget
);
892 XtVaGetValues (widget
, XmNforeground
, &fg
, NULL
);
894 M_BITMAPDATA
->m_armPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
896 return M_BITMAPDATA
->m_armPixmap
;
899 WXPixmap
wxBitmap::GetInsensPixmap (WXWidget w
)
901 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
903 if (M_BITMAPDATA
->m_insensPixmap
)
904 return M_BITMAPDATA
->m_insensPixmap
;
908 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XCreateInsensitivePixmap(dpy
, (Pixmap
) M_BITMAPDATA
->m_pixmap
);
909 if (M_BITMAPDATA
->m_insensPixmap
)
910 return M_BITMAPDATA
->m_insensPixmap
;
912 return M_BITMAPDATA
->m_pixmap
;
915 if (M_BITMAPDATA
->m_insensImage
== (WXPixmap
) 0)
916 return M_BITMAPDATA
->m_pixmap
;
919 See
GetLabelPixmap () comment
920 // Must be destroyed, because colours can have been changed!
921 if (M_BITMAPDATA
->m_insensPixmap
)
922 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), (Pixmap
) M_BITMAPDATA
->m_insensPixmap
);
926 sprintf (tmp
, "Not%x", (unsigned int) M_BITMAPDATA
->m_insensImage
);
929 Widget widget
= (Widget
) w
;
931 while (XmIsGadget (widget
))
932 widget
= XtParent (widget
);
933 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
935 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
937 return M_BITMAPDATA
->m_insensPixmap
;
940 // We may need this sometime...
942 /****************************************************************************
945 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
948 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
951 This function creates a grayed-out copy of the argument pixmap, suitable
952 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
955 The return value is the new Pixmap id or zero on error. Errors include
956 a NULL display argument or an invalid Pixmap argument.
959 If one of the XLib functions fail, it will produce a X error. The
960 default X error handler prints a diagnostic and calls exit().
963 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
964 XFillRectangle(3), exit(2)
967 John R Veregge - john@puente.jpl.nasa.gov
968 Advanced Engineering and Prototyping Group (AEG)
969 Information Systems Technology Section (395)
970 Jet Propulsion Lab - Calif Institute of Technology
972 *****************************************************************************/
975 XCreateInsensitivePixmap( Display
*display
, Pixmap pixmap
)
978 static char stipple_data
[] =
980 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
981 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
982 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
983 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
986 Pixmap ipixmap
, stipple
;
987 unsigned width
, height
, depth
;
989 Window window
; /* These return values */
990 unsigned border
; /* from XGetGeometry() */
991 int x
, y
; /* are not needed. */
995 if ( NULL
== display
|| 0 == pixmap
)
998 if ( 0 == XGetGeometry( display
, pixmap
, &window
, &x
, &y
,
999 &width
, &height
, &border
, &depth
)
1001 return ipixmap
; /* BadDrawable: probably an invalid pixmap */
1003 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
1005 stipple
= XCreateBitmapFromData( display
, pixmap
, stipple_data
, 16, 16 );
1008 gc
= XCreateGC( display
, pixmap
, (XtGCMask
)0, (XGCValues
*)NULL
);
1011 /* Create an identical copy of the argument pixmap.
1013 ipixmap
= XCreatePixmap( display
, pixmap
, width
, height
, depth
);
1016 /* Copy the argument pixmap into the new pixmap.
1018 XCopyArea( display
, pixmap
, ipixmap
,
1019 gc
, 0, 0, width
, height
, 0, 0 );
1021 /* Refill the new pixmap using the stipple algorithm/pixmap.
1023 XSetStipple( display
, gc
, stipple
);
1024 XSetFillStyle( display
, gc
, FillStippled
);
1025 XFillRectangle( display
, ipixmap
, gc
, 0, 0, width
, height
);
1027 XFreeGC( display
, gc
);
1029 XFreePixmap( display
, stipple
);
1034 // Creates a bitmap with transparent areas drawn in
1035 // the given colour.
1036 wxBitmap
wxCreateMaskedBitmap(const wxBitmap
& bitmap
, wxColour
& colour
)
1038 wxBitmap
newBitmap(bitmap
.GetWidth(),
1043 srcDC
.SelectObject(bitmap
);
1044 destDC
.SelectObject(newBitmap
);
1046 wxBrush
brush(colour
, wxSOLID
);
1047 destDC
.SetOptimization(FALSE
);
1048 destDC
.SetBackground(brush
);
1050 destDC
.Blit(0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), & srcDC
, 0, 0, wxCOPY
, TRUE
);
1058 //-----------------------------------------------------------------------------
1059 // wxImage conversion routines
1060 //-----------------------------------------------------------------------------
1064 Date: Wed, 05 Jan 2000 11:45:40 +0100
1065 From: Frits Boel <boel@niob.knaw.nl>
1066 To: julian.smart@ukonline.co.uk
1067 Subject: Patch for Motif ConvertToBitmap
1071 I've been working on a wxWin application for image processing. From the
1072 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1073 till I looked in the source code of image.cpp. I saw that converting a
1074 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1075 to the 256 colors of the palet. A very time-consuming piece of code!
1077 Because I wanted a faster application, I've made a 'patch' for this. In
1078 short: every pixel of the image is compared to a sorted list with
1079 colors. If the color is found in the list, the palette entry is
1080 returned; if the color is not found, the color palette is searched and
1081 then the palette entry is returned and the color added to the sorted
1084 Maybe there is another method for this, namely changing the palette
1085 itself (if the colors are known, as is the case with tiffs with a
1086 colormap). I did not look at this, maybe someone else did?
1088 The code of the patch is attached, have a look on it, and maybe you will
1089 ship it with the next release of wxMotif?
1094 Software engineer at Hubrecht Laboratory, The Netherlands.
1101 wxSearchColor( void );
1102 wxSearchColor( int size
, XColor
*colors
);
1103 ~wxSearchColor( void );
1105 int SearchColor( int r
, int g
, int b
);
1107 int AddColor( unsigned int value
, int pos
);
1111 unsigned int *color
;
1118 wxSearchColor::wxSearchColor( void )
1121 colors
= (XColor
*) NULL
;
1122 color
= (unsigned int *) NULL
;
1123 entry
= (int*) NULL
;
1129 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
1134 color
= new unsigned int[size
];
1135 entry
= new int [size
];
1137 for (i
= 0; i
< size
; i
++ ) {
1141 bottom
= top
= ( size
>> 1 );
1144 wxSearchColor::~wxSearchColor( void )
1146 if ( color
) delete color
;
1147 if ( entry
) delete entry
;
1150 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1152 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1157 while ( begin
<= end
) {
1159 middle
= ( begin
+ end
) >> 1;
1161 if ( value
== color
[middle
] ) {
1162 return( entry
[middle
] );
1163 } else if ( value
< color
[middle
] ) {
1171 return AddColor( value
, middle
);
1174 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1178 int max
= 3 * (65536);
1179 for ( i
= 0; i
< 256; i
++ ) {
1180 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1181 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1182 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1183 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1184 if (sum
< max
) { pixel
= i
; max
= sum
; }
1187 if ( entry
[pos
] < 0 ) {
1190 } else if ( value
< color
[pos
] ) {
1193 for ( i
= bottom
; i
< pos
; i
++ ) {
1194 color
[i
-1] = color
[i
];
1195 entry
[i
-1] = entry
[i
];
1198 color
[pos
-1] = value
;
1199 entry
[pos
-1] = pixel
;
1200 } else if ( top
< size
-1 ) {
1201 for ( i
= top
; i
>= pos
; i
-- ) {
1202 color
[i
+1] = color
[i
];
1203 entry
[i
+1] = entry
[i
];
1212 if ( top
< size
-1 ) {
1213 for ( i
= top
; i
> pos
; i
-- ) {
1214 color
[i
+1] = color
[i
];
1215 entry
[i
+1] = entry
[i
];
1218 color
[pos
+1] = value
;
1219 entry
[pos
+1] = pixel
;
1220 } else if ( bottom
> 0 ) {
1221 for ( i
= bottom
; i
< pos
; i
++ ) {
1222 color
[i
-1] = color
[i
];
1223 entry
[i
-1] = entry
[i
];
1236 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
1238 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
1239 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
1241 m_refData
= new wxBitmapRefData();
1243 int width
= image
.GetWidth();
1244 int height
= image
.GetHeight();
1246 SetHeight( height
);
1249 Display
*dpy
= (Display
*) wxGetDisplay();
1250 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1251 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1255 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1256 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1258 Create( width
, height
, bpp
);
1262 XImage
*mask_image
= (XImage
*) NULL
;
1263 if (image
.HasMask())
1265 mask_image
= XCreateImage( dpy
, vis
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1266 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
1269 // Retrieve depth info
1271 XVisualInfo vinfo_template
;
1274 vinfo_template
.visual
= vis
;
1275 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1276 vinfo_template
.depth
= bpp
;
1279 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1281 wxCHECK_MSG( vi
, FALSE
, wxT("no visual") );
1285 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1286 if (bpp
< 8) bpp
= 8;
1290 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1291 byte_order b_o
= RGB
;
1295 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1296 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1297 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1298 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1299 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1300 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1303 int r_mask
= image
.GetMaskRed();
1304 int g_mask
= image
.GetMaskGreen();
1305 int b_mask
= image
.GetMaskBlue();
1310 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1312 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1313 XQueryColors( dpy
, cmap
, colors
, 256 );
1316 wxSearchColor
scolor( 256, colors
);
1317 unsigned char* data
= image
.GetData();
1319 bool hasMask
= image
.HasMask();
1322 for (int y
= 0; y
< height
; y
++)
1324 for (int x
= 0; x
< width
; x
++)
1326 int r
= data
[index
];
1328 int g
= data
[index
];
1330 int b
= data
[index
];
1335 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1336 XPutPixel( mask_image
, x
, y
, 0 );
1338 XPutPixel( mask_image
, x
, y
, 1 );
1345 #if 0 // Old, slower code
1348 if (wxTheApp->m_colorCube)
1350 pixel = wxTheApp->m_colorCube
1351 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1356 int max
= 3 * (65536);
1357 for (int i
= 0; i
< 256; i
++)
1359 int rdiff
= (r
<< 8) - colors
[i
].red
;
1360 int gdiff
= (g
<< 8) - colors
[i
].green
;
1361 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1362 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1363 if (sum
< max
) { pixel
= i
; max
= sum
; }
1370 // And this is all to get the 'right' color...
1371 int pixel
= scolor
.SearchColor( r
, g
, b
);
1372 XPutPixel( data_image
, x
, y
, pixel
);
1377 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1378 XPutPixel( data_image
, x
, y
, pixel
);
1383 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1384 XPutPixel( data_image
, x
, y
, pixel
);
1393 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1394 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1395 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1396 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1397 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1398 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1400 XPutPixel( data_image
, x
, y
, pixel
);
1410 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1411 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1412 XPutImage( dpy
, (Drawable
)GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1414 XDestroyImage( data_image
);
1418 if (image
.HasMask())
1420 wxBitmap
maskBitmap(width
, height
, 1);
1422 GC gcMask
= XCreateGC( dpy
, (Pixmap
) maskBitmap
.GetPixmap(), (XtGCMask
) 0, (XGCValues
*)NULL
);
1423 XPutImage( dpy
, (Drawable
)maskBitmap
.GetPixmap(), gcMask
, mask_image
, 0, 0, 0, 0, width
, height
);
1425 XDestroyImage( mask_image
);
1426 XFreeGC( dpy
, gcMask
);
1428 wxMask
* mask
= new wxMask
;
1429 mask
->SetPixmap(maskBitmap
.GetPixmap());
1433 maskBitmap
.SetPixmapNull();
1440 wxImage
wxBitmap::ConvertToImage() const
1444 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
1446 Display
*dpy
= (Display
*) wxGetDisplay();
1447 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1448 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1450 XImage
*ximage
= XGetImage( dpy
,
1451 (Drawable
)GetPixmap(),
1453 GetWidth(), GetHeight(),
1454 AllPlanes
, ZPixmap
);
1456 wxCHECK_MSG( ximage
, wxNullImage
, wxT("couldn't create image") );
1458 image
.Create( GetWidth(), GetHeight() );
1459 char unsigned *data
= image
.GetData();
1463 XDestroyImage( ximage
);
1464 wxFAIL_MSG( wxT("couldn't create image") );
1469 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1472 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1474 GetWidth(), GetHeight() );
1476 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1480 // Retrieve depth info
1482 XVisualInfo vinfo_template
;
1485 vinfo_template
.visual
= vis
;
1486 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1487 vinfo_template
.depth
= bpp
;
1490 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1492 wxCHECK_MSG( vi
, wxNullImage
, wxT("no visual") );
1494 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1501 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1503 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1504 XQueryColors( dpy
, cmap
, colors
, 256 );
1508 for (int j
= 0; j
< GetHeight(); j
++)
1510 for (int i
= 0; i
< GetWidth(); i
++)
1512 int pixel
= XGetPixel( ximage
, i
, j
);
1515 data
[pos
] = colors
[pixel
].red
>> 8;
1516 data
[pos
+1] = colors
[pixel
].green
>> 8;
1517 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1518 } else if (bpp
== 15)
1520 data
[pos
] = (pixel
>> 7) & 0xf8;
1521 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1522 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1523 } else if (bpp
== 16)
1525 data
[pos
] = (pixel
>> 8) & 0xf8;
1526 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1527 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1530 data
[pos
] = (pixel
>> 16) & 0xff;
1531 data
[pos
+1] = (pixel
>> 8) & 0xff;
1532 data
[pos
+2] = pixel
& 0xff;
1538 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1539 if (mask_pixel == 0)
1552 XDestroyImage( ximage
);
1554 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );