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::CopyFromIcon(const wxIcon
& icon
)
176 bool wxBitmap::Create(int w
, int h
, int d
)
180 m_refData
= new wxBitmapRefData
;
183 d
= wxDisplayDepth();
185 M_BITMAPDATA
->m_width
= w
;
186 M_BITMAPDATA
->m_height
= h
;
187 M_BITMAPDATA
->m_depth
= d
;
188 M_BITMAPDATA
->m_freePixmap
= TRUE
;
190 Display
*dpy
= (Display
*) wxGetDisplay();
192 M_BITMAPDATA
->m_display
= dpy
; /* MATTHEW: [4] Remember the display */
194 M_BITMAPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
197 M_BITMAPDATA
->m_ok
= (M_BITMAPDATA
->m_pixmap
!= (WXPixmap
) 0) ;
198 return M_BITMAPDATA
->m_ok
;
201 bool wxBitmap::LoadFile(const wxString
& filename
, long type
)
205 m_refData
= new wxBitmapRefData
;
207 wxBitmapHandler
*handler
= FindHandler(type
);
209 if ( handler
== NULL
) {
211 if (!image
.LoadFile( filename
, type
)) return FALSE
;
214 *this = image
.ConvertToBitmap();
220 return handler
->LoadFile(this, filename
, type
, -1, -1);
223 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
)
227 m_refData
= new wxBitmapRefData
;
229 wxBitmapHandler
*handler
= FindHandler(type
);
231 if ( handler
== NULL
) {
232 wxLogWarning("no data bitmap handler for type %ld defined.", type
);
237 return handler
->Create(this, data
, type
, width
, height
, depth
);
240 bool wxBitmap::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
242 wxBitmapHandler
*handler
= FindHandler(type
);
244 if ( handler
== NULL
) { // try wxImage
245 wxImage
image( *this );
246 if (image
.Ok()) return image
.SaveFile( filename
, type
);
250 return handler
->SaveFile(this, filename
, type
, palette
);
253 void wxBitmap::SetWidth(int w
)
256 m_refData
= new wxBitmapRefData
;
258 M_BITMAPDATA
->m_width
= w
;
261 void wxBitmap::SetHeight(int h
)
264 m_refData
= new wxBitmapRefData
;
266 M_BITMAPDATA
->m_height
= h
;
269 void wxBitmap::SetDepth(int d
)
272 m_refData
= new wxBitmapRefData
;
274 M_BITMAPDATA
->m_depth
= d
;
277 void wxBitmap::SetQuality(int q
)
280 m_refData
= new wxBitmapRefData
;
282 M_BITMAPDATA
->m_quality
= q
;
285 void wxBitmap::SetOk(bool isOk
)
288 m_refData
= new wxBitmapRefData
;
290 M_BITMAPDATA
->m_ok
= isOk
;
293 void wxBitmap::SetPalette(const wxPalette
& palette
)
296 m_refData
= new wxBitmapRefData
;
298 M_BITMAPDATA
->m_bitmapPalette
= palette
;
301 void wxBitmap::SetMask(wxMask
*mask
)
304 m_refData
= new wxBitmapRefData
;
306 M_BITMAPDATA
->m_bitmapMask
= mask
;
309 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
312 (rect
.x
>= 0) && (rect
.y
>= 0) &&
313 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) && (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
314 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
316 wxBitmap
ret( rect
.width
, rect
.height
, 0 );
317 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
319 // The remaining still TODO
323 void wxBitmap::AddHandler(wxBitmapHandler
*handler
)
325 sm_handlers
.Append(handler
);
328 void wxBitmap::InsertHandler(wxBitmapHandler
*handler
)
330 sm_handlers
.Insert(handler
);
333 bool wxBitmap::RemoveHandler(const wxString
& name
)
335 wxBitmapHandler
*handler
= FindHandler(name
);
338 sm_handlers
.DeleteObject(handler
);
345 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& name
)
347 wxNode
*node
= sm_handlers
.First();
350 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
351 if ( handler
->GetName() == name
)
358 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& extension
, long bitmapType
)
360 wxNode
*node
= sm_handlers
.First();
363 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
364 if ( handler
->GetExtension() == extension
&&
365 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
372 wxBitmapHandler
*wxBitmap::FindHandler(long bitmapType
)
374 wxNode
*node
= sm_handlers
.First();
377 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
378 if (handler
->GetType() == bitmapType
)
391 m_pixmap
= (WXPixmap
) 0;
394 // Construct a mask from a bitmap and a colour indicating
395 // the transparent area
396 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
398 m_pixmap
= (WXPixmap
) 0;
400 Create(bitmap
, colour
);
403 // Construct a mask from a bitmap and a palette index indicating
404 // the transparent area
405 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
407 m_pixmap
= (WXPixmap
) 0;
409 Create(bitmap
, paletteIndex
);
412 // Construct a mask from a mono bitmap (copies the bitmap).
413 wxMask::wxMask(const wxBitmap
& bitmap
)
415 m_pixmap
= (WXPixmap
) 0;
422 // TODO: this may be the wrong display
424 XFreePixmap ((Display
*) wxGetDisplay(), (Pixmap
) m_pixmap
);
427 // Create a mask from a mono bitmap (copies the bitmap).
428 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
))
434 // Create a mask from a bitmap and a palette index indicating
435 // the transparent area
436 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), int WXUNUSED(paletteIndex
))
442 // Create a mask from a bitmap and a colour indicating
443 // the transparent area
444 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), const wxColour
& WXUNUSED(colour
))
454 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
456 bool wxBitmapHandler::Create(wxBitmap
*WXUNUSED(bitmap
), void *WXUNUSED(data
), long WXUNUSED(type
),
457 int WXUNUSED(width
), int WXUNUSED(height
), int WXUNUSED(depth
))
462 bool wxBitmapHandler::LoadFile(wxBitmap
*WXUNUSED(bitmap
), const wxString
& WXUNUSED(name
), long WXUNUSED(type
),
463 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
468 bool wxBitmapHandler::SaveFile(wxBitmap
*WXUNUSED(bitmap
), const wxString
& WXUNUSED(name
), int WXUNUSED(type
),
469 const wxPalette
*WXUNUSED(palette
))
478 class WXDLLEXPORT wxXBMFileHandler
: public wxBitmapHandler
480 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler
)
482 inline wxXBMFileHandler()
486 m_type
= wxBITMAP_TYPE_XBM
;
489 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
490 int desiredWidth
, int desiredHeight
);
492 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler
, wxBitmapHandler
)
494 bool wxXBMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long WXUNUSED(flags
),
495 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
497 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
503 Display
*dpy
= (Display
*) wxGetDisplay();
504 M_BITMAPDATA
->m_display
= (WXDisplay
*) dpy
;
506 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
507 (char*) (const char*) name
, &w
, &h
, &pixmap
, &hotX
, &hotY
);
508 M_BITMAPHANDLERDATA
->m_width
= w
;
509 M_BITMAPHANDLERDATA
->m_height
= h
;
510 M_BITMAPHANDLERDATA
->m_depth
= 1;
511 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
513 if ((value
== BitmapFileInvalid
) ||
514 (value
== BitmapOpenFailed
) ||
515 (value
== BitmapNoMemory
))
517 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
518 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) 0;
521 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
523 return M_BITMAPHANDLERDATA
->m_ok
;
526 class WXDLLEXPORT wxXBMDataHandler
: public wxBitmapHandler
528 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler
)
530 inline wxXBMDataHandler()
534 m_type
= wxBITMAP_TYPE_XBM_DATA
;
537 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
, int width
, int height
, int depth
= 1);
539 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler
, wxBitmapHandler
)
541 bool wxXBMDataHandler::Create( wxBitmap
*bitmap
, void *data
, long WXUNUSED(flags
),
542 int width
, int height
, int WXUNUSED(depth
))
544 M_BITMAPHANDLERDATA
->m_width
= width
;
545 M_BITMAPHANDLERDATA
->m_height
= height
;
546 M_BITMAPHANDLERDATA
->m_depth
= 1;
547 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
549 Display
*dpy
= (Display
*) wxGetDisplay();
550 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
552 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) XCreateBitmapFromData (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)), (char*) data
, width
, height
);
553 M_BITMAPHANDLERDATA
->m_ok
= (M_BITMAPHANDLERDATA
->m_pixmap
!= (WXPixmap
) 0) ;
555 // code for wxControl. TODO: can we avoid doing this until we need it?
556 // E.g. have CreateButtonPixmaps which is called on demand.
557 XImage
* image
= (XImage
*) XtMalloc (sizeof (XImage
));
558 image
->width
= width
;
559 image
->height
= height
;
560 image
->data
= (char*) data
;
563 image
->format
= XYBitmap
;
564 image
->byte_order
= LSBFirst
;
565 image
->bitmap_unit
= 8;
566 image
->bitmap_bit_order
= LSBFirst
;
567 image
->bitmap_pad
= 8;
568 image
->bytes_per_line
= (width
+ 7) >> 3;
571 sprintf (tmp
, "Im%x", (unsigned int) image
);
572 XmInstallImage (image
, tmp
);
574 // Build our manually stipped pixmap.
576 int bpl
= (width
+ 7) / 8;
577 char *data1
= new char[height
* bpl
];
578 char* bits
= (char*) data
;
580 for (i
= 0; i
< height
; i
++)
582 int mask
= i
% 2 ? 0x55 : 0xaa;
584 for (j
= 0; j
< bpl
; j
++)
585 data1
[i
* bpl
+ j
] = bits
[i
* bpl
+ j
] & mask
;
587 XImage
* insensImage
= (XImage
*) XtMalloc (sizeof (XImage
));
588 insensImage
->width
= width
;
589 insensImage
->height
= height
;
590 insensImage
->data
= data1
;
591 insensImage
->depth
= 1;
592 insensImage
->xoffset
= 0;
593 insensImage
->format
= XYBitmap
;
594 insensImage
->byte_order
= LSBFirst
;
595 insensImage
->bitmap_unit
= 8;
596 insensImage
->bitmap_bit_order
= LSBFirst
;
597 insensImage
->bitmap_pad
= 8;
598 insensImage
->bytes_per_line
= bpl
;
600 sprintf (tmp
, "Not%x", (unsigned int)insensImage
);
601 XmInstallImage (insensImage
, tmp
);
603 M_BITMAPHANDLERDATA
->m_image
= (WXImage
*) image
;
604 M_BITMAPHANDLERDATA
->m_insensImage
= (WXImage
*) insensImage
;
610 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
612 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
614 inline wxXPMFileHandler()
618 m_type
= wxBITMAP_TYPE_XPM
;
621 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
622 int desiredWidth
, int desiredHeight
);
623 virtual bool SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*palette
= NULL
);
626 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
628 bool wxXPMFileHandler::LoadFile( wxBitmap
*bitmap
, const wxString
& name
, long WXUNUSED(flags
),
629 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
) )
631 Display
*dpy
= (Display
*) wxGetDisplay();
632 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
634 XpmAttributes xpmAttr
;
638 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
639 xpmAttr
.valuemask
= XpmReturnInfos
| XpmCloseness
;
640 xpmAttr
.closeness
= 40000;
641 int errorStatus
= XpmReadFileToPixmap(dpy
,
642 RootWindow(dpy
, DefaultScreen(dpy
)), (char*) (const char*) name
,
643 &pixmap
, &mask
, &xpmAttr
);
645 if (errorStatus
== XpmSuccess
)
647 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
650 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
651 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
654 unsigned int depthRet
;
656 unsigned int widthRet
, heightRet
, borderWidthRet
;
657 Window rootWindowRet
;
658 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
659 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
661 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
662 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
665 if ( xpmAttr.npixels > 2 )
667 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
670 M_BITMAPHANDLERDATA->m_depth = 1; // mono
674 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
676 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
678 XpmFreeAttributes(&xpmAttr
);
680 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
684 // XpmDebugError(errorStatus, name);
685 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
690 bool wxXPMFileHandler::SaveFile( wxBitmap
*bitmap
, const wxString
& name
, int WXUNUSED(type
),
691 const wxPalette
*WXUNUSED(palette
))
693 if (M_BITMAPHANDLERDATA
->m_ok
&& M_BITMAPHANDLERDATA
->m_pixmap
)
695 Display
*dpy
= (Display
*) M_BITMAPHANDLERDATA
->m_display
;
696 int errorStatus
= XpmWriteFileFromPixmap(dpy
, (char*) (const char*) name
,
697 (Pixmap
) M_BITMAPHANDLERDATA
->m_pixmap
,
698 (M_BITMAPHANDLERDATA
->m_bitmapMask
? (Pixmap
) M_BITMAPHANDLERDATA
->m_bitmapMask
->GetPixmap() : (Pixmap
) 0),
699 (XpmAttributes
*) NULL
);
700 if (errorStatus
== XpmSuccess
)
709 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
711 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
713 inline wxXPMDataHandler()
717 m_type
= wxBITMAP_TYPE_XPM_DATA
;
720 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
, int width
, int height
, int depth
= 1);
722 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
724 bool wxXPMDataHandler::Create( wxBitmap
*bitmap
, void *data
, long WXUNUSED(flags
),
725 int width
, int height
, int WXUNUSED(depth
))
727 M_BITMAPHANDLERDATA
->m_width
= width
;
728 M_BITMAPHANDLERDATA
->m_height
= height
;
729 M_BITMAPHANDLERDATA
->m_depth
= 1;
730 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
732 Display
*dpy
= (Display
*) wxGetDisplay();
733 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
735 XpmAttributes xpmAttr
;
737 xpmAttr
.valuemask
= XpmReturnInfos
; /* nothing yet, but get infos back */
739 XpmColorSymbol symbolicColors
[4];
740 if (sg_Control
&& sg_Control
->GetMainWidget())
742 symbolicColors
[0].name
= "foreground";
743 symbolicColors
[0].value
= NULL
;
744 symbolicColors
[1].name
= "background";
745 symbolicColors
[1].value
= NULL
;
746 XtVaGetValues((Widget
) sg_Control
->GetMainWidget(),
747 XmNforeground
, &symbolicColors
[0].pixel
,
748 XmNbackground
, &symbolicColors
[1].pixel
,NULL
);
749 xpmAttr
.numsymbols
= 2;
750 xpmAttr
.colorsymbols
= symbolicColors
;
751 xpmAttr
.valuemask
|= XpmColorSymbols
; // add flag
756 int ErrorStatus
= XpmCreatePixmapFromData(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)),
757 (char**) data
, &pixmap
, &mask
, &xpmAttr
);
758 if (ErrorStatus
== XpmSuccess
)
761 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
762 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
764 unsigned int depthRet
;
766 unsigned int widthRet
, heightRet
, borderWidthRet
;
767 Window rootWindowRet
;
768 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
769 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
772 if ( xpmAttr.npixels > 2 )
774 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
777 M_BITMAPHANDLERDATA->m_depth = 1; // mono
781 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
783 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
784 XpmFreeAttributes(&xpmAttr
);
785 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
786 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
789 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
790 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
795 // XpmDebugError(ErrorStatus, NULL);
796 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
798 return M_BITMAPHANDLERDATA
->m_ok
;
801 #endif // wxHAVE_LIB_XPM
803 void wxBitmap::CleanUpHandlers()
805 wxNode
*node
= sm_handlers
.First();
808 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
809 wxNode
*next
= node
->Next();
816 void wxBitmap::InitStandardHandlers()
818 // Initialize all standard bitmap or derived class handlers here.
819 AddHandler(new wxXBMFileHandler
);
820 AddHandler(new wxXBMDataHandler
);
822 // XPM is considered standard for Motif, although it can be omitted if
823 // libXpm is not installed
825 AddHandler(new wxXPMFileHandler
);
826 AddHandler(new wxXPMDataHandler
);
827 #endif // wxHAVE_LIB_XPM
830 WXPixmap
wxBitmap::GetLabelPixmap (WXWidget w
)
832 if (M_BITMAPDATA
->m_image
== (WXPixmap
) 0)
833 return M_BITMAPDATA
->m_pixmap
;
835 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
840 if (labelPixmap) return labelPixmap;
841 things can be wrong, because colors can have been changed.
845 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
846 we got BadDrawable if the pixmap is referenced by multiples widgets
850 So, before doing thing really clean, I just do nothing; if the pixmap is
851 referenced by many widgets, Motif performs caching functions.
852 And if pixmap is referenced with multiples colors, we just have some
853 memory leaks... I hope we can deal with them...
855 // Must be destroyed, because colours can have been changed!
856 if (M_BITMAPDATA
->m_labelPixmap
)
857 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_labelPixmap
);
861 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
864 Widget widget
= (Widget
) w
;
866 while (XmIsGadget ( widget
))
867 widget
= XtParent (widget
);
868 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
870 M_BITMAPDATA
->m_labelPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
872 return M_BITMAPDATA
->m_labelPixmap
;
875 WXPixmap
wxBitmap::GetArmPixmap (WXWidget w
)
877 if (M_BITMAPDATA
->m_image
== (WXPixmap
) 0)
878 return M_BITMAPDATA
->m_pixmap
;
880 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
882 // See GetLabelPixmap () comment
884 // Must be destroyed, because colours can have been changed!
885 if (M_BITMAPDATA
->m_armPixmap
)
886 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_armPixmap
);
890 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
893 Widget widget
= (Widget
) w
;
895 XtVaGetValues (widget
, XmNarmColor
, &bg
, NULL
);
896 while (XmIsGadget (widget
))
897 widget
= XtParent (widget
);
898 XtVaGetValues (widget
, XmNforeground
, &fg
, NULL
);
900 M_BITMAPDATA
->m_armPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
902 return M_BITMAPDATA
->m_armPixmap
;
905 WXPixmap
wxBitmap::GetInsensPixmap (WXWidget w
)
907 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
909 if (M_BITMAPDATA
->m_insensPixmap
)
910 return M_BITMAPDATA
->m_insensPixmap
;
914 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XCreateInsensitivePixmap(dpy
, (Pixmap
) M_BITMAPDATA
->m_pixmap
);
915 if (M_BITMAPDATA
->m_insensPixmap
)
916 return M_BITMAPDATA
->m_insensPixmap
;
918 return M_BITMAPDATA
->m_pixmap
;
921 if (M_BITMAPDATA
->m_insensImage
== (WXPixmap
) 0)
922 return M_BITMAPDATA
->m_pixmap
;
925 See
GetLabelPixmap () comment
926 // Must be destroyed, because colours can have been changed!
927 if (M_BITMAPDATA
->m_insensPixmap
)
928 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), (Pixmap
) M_BITMAPDATA
->m_insensPixmap
);
932 sprintf (tmp
, "Not%x", (unsigned int) M_BITMAPDATA
->m_insensImage
);
935 Widget widget
= (Widget
) w
;
937 while (XmIsGadget (widget
))
938 widget
= XtParent (widget
);
939 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
941 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
943 return M_BITMAPDATA
->m_insensPixmap
;
946 // We may need this sometime...
948 /****************************************************************************
951 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
954 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
957 This function creates a grayed-out copy of the argument pixmap, suitable
958 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
961 The return value is the new Pixmap id or zero on error. Errors include
962 a NULL display argument or an invalid Pixmap argument.
965 If one of the XLib functions fail, it will produce a X error. The
966 default X error handler prints a diagnostic and calls exit().
969 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
970 XFillRectangle(3), exit(2)
973 John R Veregge - john@puente.jpl.nasa.gov
974 Advanced Engineering and Prototyping Group (AEG)
975 Information Systems Technology Section (395)
976 Jet Propulsion Lab - Calif Institute of Technology
978 *****************************************************************************/
981 XCreateInsensitivePixmap( Display
*display
, Pixmap pixmap
)
984 static char stipple_data
[] =
986 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
987 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
988 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
989 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
992 Pixmap ipixmap
, stipple
;
993 unsigned width
, height
, depth
;
995 Window window
; /* These return values */
996 unsigned border
; /* from XGetGeometry() */
997 int x
, y
; /* are not needed. */
1001 if ( NULL
== display
|| 0 == pixmap
)
1004 if ( 0 == XGetGeometry( display
, pixmap
, &window
, &x
, &y
,
1005 &width
, &height
, &border
, &depth
)
1007 return ipixmap
; /* BadDrawable: probably an invalid pixmap */
1009 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
1011 stipple
= XCreateBitmapFromData( display
, pixmap
, stipple_data
, 16, 16 );
1014 gc
= XCreateGC( display
, pixmap
, (XtGCMask
)0, (XGCValues
*)NULL
);
1017 /* Create an identical copy of the argument pixmap.
1019 ipixmap
= XCreatePixmap( display
, pixmap
, width
, height
, depth
);
1022 /* Copy the argument pixmap into the new pixmap.
1024 XCopyArea( display
, pixmap
, ipixmap
,
1025 gc
, 0, 0, width
, height
, 0, 0 );
1027 /* Refill the new pixmap using the stipple algorithm/pixmap.
1029 XSetStipple( display
, gc
, stipple
);
1030 XSetFillStyle( display
, gc
, FillStippled
);
1031 XFillRectangle( display
, ipixmap
, gc
, 0, 0, width
, height
);
1033 XFreeGC( display
, gc
);
1035 XFreePixmap( display
, stipple
);
1040 // Creates a bitmap with transparent areas drawn in
1041 // the given colour.
1042 wxBitmap
wxCreateMaskedBitmap(const wxBitmap
& bitmap
, wxColour
& colour
)
1044 wxBitmap
newBitmap(bitmap
.GetWidth(),
1049 srcDC
.SelectObject(bitmap
);
1050 destDC
.SelectObject(newBitmap
);
1052 wxBrush
brush(colour
, wxSOLID
);
1053 destDC
.SetOptimization(FALSE
);
1054 destDC
.SetBackground(brush
);
1056 destDC
.Blit(0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), & srcDC
, 0, 0, wxCOPY
, TRUE
);
1064 //-----------------------------------------------------------------------------
1065 // wxImage conversion routines
1066 //-----------------------------------------------------------------------------
1070 Date: Wed, 05 Jan 2000 11:45:40 +0100
1071 From: Frits Boel <boel@niob.knaw.nl>
1072 To: julian.smart@ukonline.co.uk
1073 Subject: Patch for Motif ConvertToBitmap
1077 I've been working on a wxWin application for image processing. From the
1078 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1079 till I looked in the source code of image.cpp. I saw that converting a
1080 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1081 to the 256 colors of the palet. A very time-consuming piece of code!
1083 Because I wanted a faster application, I've made a 'patch' for this. In
1084 short: every pixel of the image is compared to a sorted list with
1085 colors. If the color is found in the list, the palette entry is
1086 returned; if the color is not found, the color palette is searched and
1087 then the palette entry is returned and the color added to the sorted
1090 Maybe there is another method for this, namely changing the palette
1091 itself (if the colors are known, as is the case with tiffs with a
1092 colormap). I did not look at this, maybe someone else did?
1094 The code of the patch is attached, have a look on it, and maybe you will
1095 ship it with the next release of wxMotif?
1100 Software engineer at Hubrecht Laboratory, The Netherlands.
1107 wxSearchColor( void );
1108 wxSearchColor( int size
, XColor
*colors
);
1109 ~wxSearchColor( void );
1111 int SearchColor( int r
, int g
, int b
);
1113 int AddColor( unsigned int value
, int pos
);
1117 unsigned int *color
;
1124 wxSearchColor::wxSearchColor( void )
1127 colors
= (XColor
*) NULL
;
1128 color
= (unsigned int *) NULL
;
1129 entry
= (int*) NULL
;
1135 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
1140 color
= new unsigned int[size
];
1141 entry
= new int [size
];
1143 for (i
= 0; i
< size
; i
++ ) {
1147 bottom
= top
= ( size
>> 1 );
1150 wxSearchColor::~wxSearchColor( void )
1152 if ( color
) delete color
;
1153 if ( entry
) delete entry
;
1156 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1158 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1163 while ( begin
<= end
) {
1165 middle
= ( begin
+ end
) >> 1;
1167 if ( value
== color
[middle
] ) {
1168 return( entry
[middle
] );
1169 } else if ( value
< color
[middle
] ) {
1177 return AddColor( value
, middle
);
1180 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1184 int max
= 3 * (65536);
1185 for ( i
= 0; i
< 256; i
++ ) {
1186 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1187 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1188 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1189 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1190 if (sum
< max
) { pixel
= i
; max
= sum
; }
1193 if ( entry
[pos
] < 0 ) {
1196 } else if ( value
< color
[pos
] ) {
1199 for ( i
= bottom
; i
< pos
; i
++ ) {
1200 color
[i
-1] = color
[i
];
1201 entry
[i
-1] = entry
[i
];
1204 color
[pos
-1] = value
;
1205 entry
[pos
-1] = pixel
;
1206 } else if ( top
< size
-1 ) {
1207 for ( i
= top
; i
>= pos
; i
-- ) {
1208 color
[i
+1] = color
[i
];
1209 entry
[i
+1] = entry
[i
];
1218 if ( top
< size
-1 ) {
1219 for ( i
= top
; i
> pos
; i
-- ) {
1220 color
[i
+1] = color
[i
];
1221 entry
[i
+1] = entry
[i
];
1224 color
[pos
+1] = value
;
1225 entry
[pos
+1] = pixel
;
1226 } else if ( bottom
> 0 ) {
1227 for ( i
= bottom
; i
< pos
; i
++ ) {
1228 color
[i
-1] = color
[i
];
1229 entry
[i
-1] = entry
[i
];
1242 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
1244 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
1245 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
1247 m_refData
= new wxBitmapRefData();
1249 int width
= image
.GetWidth();
1250 int height
= image
.GetHeight();
1252 SetHeight( height
);
1255 Display
*dpy
= (Display
*) wxGetDisplay();
1256 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1257 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1261 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1262 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1264 Create( width
, height
, bpp
);
1268 XImage
*mask_image
= (XImage
*) NULL
;
1269 if (image
.HasMask())
1271 mask_image
= XCreateImage( dpy
, vis
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1272 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
1275 // Retrieve depth info
1277 XVisualInfo vinfo_template
;
1280 vinfo_template
.visual
= vis
;
1281 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1282 vinfo_template
.depth
= bpp
;
1285 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1287 wxCHECK_MSG( vi
, FALSE
, wxT("no visual") );
1291 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1292 if (bpp
< 8) bpp
= 8;
1296 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1297 byte_order b_o
= RGB
;
1301 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1302 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1303 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1304 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1305 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1306 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1309 int r_mask
= image
.GetMaskRed();
1310 int g_mask
= image
.GetMaskGreen();
1311 int b_mask
= image
.GetMaskBlue();
1316 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1318 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1319 XQueryColors( dpy
, cmap
, colors
, 256 );
1322 wxSearchColor
scolor( 256, colors
);
1323 unsigned char* data
= image
.GetData();
1325 bool hasMask
= image
.HasMask();
1328 for (int y
= 0; y
< height
; y
++)
1330 for (int x
= 0; x
< width
; x
++)
1332 int r
= data
[index
];
1334 int g
= data
[index
];
1336 int b
= data
[index
];
1341 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1342 XPutPixel( mask_image
, x
, y
, 0 );
1344 XPutPixel( mask_image
, x
, y
, 1 );
1351 #if 0 // Old, slower code
1354 if (wxTheApp->m_colorCube)
1356 pixel = wxTheApp->m_colorCube
1357 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1362 int max
= 3 * (65536);
1363 for (int i
= 0; i
< 256; i
++)
1365 int rdiff
= (r
<< 8) - colors
[i
].red
;
1366 int gdiff
= (g
<< 8) - colors
[i
].green
;
1367 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1368 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1369 if (sum
< max
) { pixel
= i
; max
= sum
; }
1376 // And this is all to get the 'right' color...
1377 int pixel
= scolor
.SearchColor( r
, g
, b
);
1378 XPutPixel( data_image
, x
, y
, pixel
);
1383 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1384 XPutPixel( data_image
, x
, y
, pixel
);
1389 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1390 XPutPixel( data_image
, x
, y
, pixel
);
1399 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1400 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1401 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1402 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1403 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1404 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1406 XPutPixel( data_image
, x
, y
, pixel
);
1416 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1417 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1418 XPutImage( dpy
, (Drawable
)GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1420 XDestroyImage( data_image
);
1424 if (image
.HasMask())
1426 wxBitmap
maskBitmap(width
, height
, 1);
1428 GC gcMask
= XCreateGC( dpy
, (Pixmap
) maskBitmap
.GetPixmap(), (XtGCMask
) 0, (XGCValues
*)NULL
);
1429 XPutImage( dpy
, (Drawable
)maskBitmap
.GetPixmap(), gcMask
, mask_image
, 0, 0, 0, 0, width
, height
);
1431 XDestroyImage( mask_image
);
1432 XFreeGC( dpy
, gcMask
);
1434 wxMask
* mask
= new wxMask
;
1435 mask
->SetPixmap(maskBitmap
.GetPixmap());
1439 maskBitmap
.SetPixmapNull();
1446 wxImage
wxBitmap::ConvertToImage() const
1450 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
1452 Display
*dpy
= (Display
*) wxGetDisplay();
1453 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1454 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1456 XImage
*ximage
= XGetImage( dpy
,
1457 (Drawable
)GetPixmap(),
1459 GetWidth(), GetHeight(),
1460 AllPlanes
, ZPixmap
);
1462 wxCHECK_MSG( ximage
, wxNullImage
, wxT("couldn't create image") );
1464 image
.Create( GetWidth(), GetHeight() );
1465 char unsigned *data
= image
.GetData();
1469 XDestroyImage( ximage
);
1470 wxFAIL_MSG( wxT("couldn't create image") );
1475 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1478 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1480 GetWidth(), GetHeight() );
1482 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1486 // Retrieve depth info
1488 XVisualInfo vinfo_template
;
1491 vinfo_template
.visual
= vis
;
1492 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1493 vinfo_template
.depth
= bpp
;
1496 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1498 wxCHECK_MSG( vi
, wxNullImage
, wxT("no visual") );
1500 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1507 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1509 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1510 XQueryColors( dpy
, cmap
, colors
, 256 );
1514 for (int j
= 0; j
< GetHeight(); j
++)
1516 for (int i
= 0; i
< GetWidth(); i
++)
1518 int pixel
= XGetPixel( ximage
, i
, j
);
1521 data
[pos
] = colors
[pixel
].red
>> 8;
1522 data
[pos
+1] = colors
[pixel
].green
>> 8;
1523 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1524 } else if (bpp
== 15)
1526 data
[pos
] = (pixel
>> 7) & 0xf8;
1527 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1528 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1529 } else if (bpp
== 16)
1531 data
[pos
] = (pixel
>> 8) & 0xf8;
1532 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1533 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1536 data
[pos
] = (pixel
>> 16) & 0xff;
1537 data
[pos
+1] = (pixel
>> 8) & 0xff;
1538 data
[pos
+2] = pixel
& 0xff;
1544 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1545 if (mask_pixel == 0)
1558 XDestroyImage( ximage
);
1560 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );