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 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
123 wxBitmap::~wxBitmap()
127 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
129 m_refData
= new wxBitmapRefData
;
131 (void) Create((void*) bits
, wxBITMAP_TYPE_XBM_DATA
, width
, height
, depth
);
134 wxBitmap::wxBitmap(int w
, int h
, int d
)
136 (void)Create(w
, h
, d
);
139 wxBitmap::wxBitmap(void *data
, wxBitmapType type
,
140 int width
, int height
, int depth
)
142 (void) Create(data
, type
, width
, height
, depth
);
145 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
)
147 LoadFile(filename
, type
);
150 // Create from XPM data
151 static wxControl
* sg_Control
= NULL
;
152 wxBitmap::wxBitmap(char **data
, wxControl
* control
)
154 // Pass the control to the Create function using a global
155 sg_Control
= control
;
157 (void) Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
159 sg_Control
= (wxControl
*) NULL
;
162 bool wxBitmap::CreateFromXpm(const char **bits
)
164 wxCHECK_MSG( bits
, FALSE
, _T("NULL pointer in wxBitmap::CreateFromXpm") );
166 return Create(bits
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
169 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
175 bool wxBitmap::Create(int w
, int h
, int d
)
179 m_refData
= new wxBitmapRefData
;
182 d
= wxDisplayDepth();
184 M_BITMAPDATA
->m_width
= w
;
185 M_BITMAPDATA
->m_height
= h
;
186 M_BITMAPDATA
->m_depth
= d
;
187 M_BITMAPDATA
->m_freePixmap
= TRUE
;
189 Display
*dpy
= (Display
*) wxGetDisplay();
191 M_BITMAPDATA
->m_display
= dpy
; /* MATTHEW: [4] Remember the display */
193 M_BITMAPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
196 M_BITMAPDATA
->m_ok
= (M_BITMAPDATA
->m_pixmap
!= (WXPixmap
) 0) ;
197 return M_BITMAPDATA
->m_ok
;
200 bool wxBitmap::LoadFile(const wxString
& filename
, wxBitmapType type
)
204 m_refData
= new wxBitmapRefData
;
206 wxBitmapHandler
*handler
= FindHandler(type
);
208 if ( handler
== NULL
) {
210 if (!image
.LoadFile( filename
, type
)) return FALSE
;
213 *this = wxBitmap(image
);
219 return handler
->LoadFile(this, filename
, type
, -1, -1);
222 bool wxBitmap::Create(void *data
, wxBitmapType type
,
223 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.",
238 return handler
->Create(this, data
, type
, width
, height
, depth
);
241 bool wxBitmap::SaveFile(const wxString
& filename
, wxBitmapType type
,
242 const wxPalette
*palette
) const
244 wxBitmapHandler
*handler
= FindHandler(type
);
246 if ( handler
== NULL
) { // try wxImage
247 wxImage image
= this->ConvertToImage();
248 if (image
.Ok()) return image
.SaveFile( filename
, type
);
252 return handler
->SaveFile(this, filename
, type
, palette
);
255 void wxBitmap::SetWidth(int w
)
258 m_refData
= new wxBitmapRefData
;
260 M_BITMAPDATA
->m_width
= w
;
263 void wxBitmap::SetHeight(int h
)
266 m_refData
= new wxBitmapRefData
;
268 M_BITMAPDATA
->m_height
= h
;
271 void wxBitmap::SetDepth(int d
)
274 m_refData
= new wxBitmapRefData
;
276 M_BITMAPDATA
->m_depth
= d
;
279 void wxBitmap::SetQuality(int q
)
282 m_refData
= new wxBitmapRefData
;
284 M_BITMAPDATA
->m_quality
= q
;
287 void wxBitmap::SetOk(bool isOk
)
290 m_refData
= new wxBitmapRefData
;
292 M_BITMAPDATA
->m_ok
= isOk
;
295 void wxBitmap::SetPalette(const wxPalette
& palette
)
298 m_refData
= new wxBitmapRefData
;
300 M_BITMAPDATA
->m_bitmapPalette
= palette
;
303 void wxBitmap::SetMask(wxMask
*mask
)
306 m_refData
= new wxBitmapRefData
;
308 M_BITMAPDATA
->m_bitmapMask
= mask
;
311 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
314 (rect
.x
>= 0) && (rect
.y
>= 0) &&
315 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) && (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
316 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
318 wxBitmap
ret( rect
.width
, rect
.height
, 0 );
319 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
321 // The remaining still TODO
331 m_pixmap
= (WXPixmap
) 0;
334 // Construct a mask from a bitmap and a colour indicating
335 // the transparent area
336 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
338 m_pixmap
= (WXPixmap
) 0;
340 Create(bitmap
, colour
);
343 // Construct a mask from a bitmap and a palette index indicating
344 // the transparent area
345 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
347 m_pixmap
= (WXPixmap
) 0;
349 Create(bitmap
, paletteIndex
);
352 // Construct a mask from a mono bitmap (copies the bitmap).
353 wxMask::wxMask(const wxBitmap
& bitmap
)
355 m_pixmap
= (WXPixmap
) 0;
362 // TODO: this may be the wrong display
364 XFreePixmap ((Display
*) wxGetDisplay(), (Pixmap
) m_pixmap
);
367 // Create a mask from a mono bitmap (copies the bitmap).
368 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
))
374 // Create a mask from a bitmap and a palette index indicating
375 // the transparent area
376 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), int WXUNUSED(paletteIndex
))
382 // Create a mask from a bitmap and a colour indicating
383 // the transparent area
384 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), const wxColour
& WXUNUSED(colour
))
394 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
400 class WXDLLEXPORT wxXBMFileHandler
: public wxBitmapHandler
402 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler
)
404 inline wxXBMFileHandler()
408 m_type
= wxBITMAP_TYPE_XBM
;
411 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
412 int desiredWidth
, int desiredHeight
);
415 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler
, wxBitmapHandler
)
417 bool wxXBMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
,
418 long WXUNUSED(flags
),
419 int WXUNUSED(desiredWidth
),
420 int WXUNUSED(desiredHeight
))
422 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
428 Display
*dpy
= (Display
*) wxGetDisplay();
429 M_BITMAPDATA
->m_display
= (WXDisplay
*) dpy
;
431 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
432 (char*) (const char*) name
, &w
, &h
, &pixmap
, &hotX
, &hotY
);
433 M_BITMAPHANDLERDATA
->m_width
= w
;
434 M_BITMAPHANDLERDATA
->m_height
= h
;
435 M_BITMAPHANDLERDATA
->m_depth
= 1;
436 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
438 if ((value
== BitmapFileInvalid
) ||
439 (value
== BitmapOpenFailed
) ||
440 (value
== BitmapNoMemory
))
442 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
443 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) 0;
446 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
448 return M_BITMAPHANDLERDATA
->m_ok
;
451 class WXDLLEXPORT wxXBMDataHandler
: public wxBitmapHandler
453 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler
)
455 inline wxXBMDataHandler()
459 m_type
= wxBITMAP_TYPE_XBM_DATA
;
462 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
463 int width
, int height
, int depth
= 1);
465 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler
, wxBitmapHandler
)
467 bool wxXBMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
468 long WXUNUSED(flags
),
469 int width
, int height
, int WXUNUSED(depth
))
471 M_BITMAPHANDLERDATA
->m_width
= width
;
472 M_BITMAPHANDLERDATA
->m_height
= height
;
473 M_BITMAPHANDLERDATA
->m_depth
= 1;
474 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
476 Display
*dpy
= (Display
*) wxGetDisplay();
477 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
479 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) XCreateBitmapFromData (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)), (char*) data
, width
, height
);
480 M_BITMAPHANDLERDATA
->m_ok
= (M_BITMAPHANDLERDATA
->m_pixmap
!= (WXPixmap
) 0) ;
482 // code for wxControl. TODO: can we avoid doing this until we need it?
483 // E.g. have CreateButtonPixmaps which is called on demand.
484 XImage
* image
= (XImage
*) XtMalloc (sizeof (XImage
));
485 image
->width
= width
;
486 image
->height
= height
;
487 image
->data
= (char*) data
;
490 image
->format
= XYBitmap
;
491 image
->byte_order
= LSBFirst
;
492 image
->bitmap_unit
= 8;
493 image
->bitmap_bit_order
= LSBFirst
;
494 image
->bitmap_pad
= 8;
495 image
->bytes_per_line
= (width
+ 7) >> 3;
498 sprintf (tmp
, "Im%x", (unsigned int) image
);
499 XmInstallImage (image
, tmp
);
501 // Build our manually stipped pixmap.
503 int bpl
= (width
+ 7) / 8;
504 char *data1
= new char[height
* bpl
];
505 char* bits
= (char*) data
;
507 for (i
= 0; i
< height
; i
++)
509 int mask
= i
% 2 ? 0x55 : 0xaa;
511 for (j
= 0; j
< bpl
; j
++)
512 data1
[i
* bpl
+ j
] = bits
[i
* bpl
+ j
] & mask
;
514 XImage
* insensImage
= (XImage
*) XtMalloc (sizeof (XImage
));
515 insensImage
->width
= width
;
516 insensImage
->height
= height
;
517 insensImage
->data
= data1
;
518 insensImage
->depth
= 1;
519 insensImage
->xoffset
= 0;
520 insensImage
->format
= XYBitmap
;
521 insensImage
->byte_order
= LSBFirst
;
522 insensImage
->bitmap_unit
= 8;
523 insensImage
->bitmap_bit_order
= LSBFirst
;
524 insensImage
->bitmap_pad
= 8;
525 insensImage
->bytes_per_line
= bpl
;
527 sprintf (tmp
, "Not%x", (unsigned int)insensImage
);
528 XmInstallImage (insensImage
, tmp
);
530 M_BITMAPHANDLERDATA
->m_image
= (WXImage
*) image
;
531 M_BITMAPHANDLERDATA
->m_insensImage
= (WXImage
*) insensImage
;
537 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
539 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
541 inline wxXPMFileHandler()
545 m_type
= wxBITMAP_TYPE_XPM
;
548 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
549 int desiredWidth
, int desiredHeight
);
550 virtual bool SaveFile(const wxBitmap
*bitmap
, const wxString
& name
,
551 wxBitmapType type
, const wxPalette
*palette
= NULL
);
554 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
556 bool wxXPMFileHandler::LoadFile( wxBitmap
*bitmap
, const wxString
& name
,
557 long WXUNUSED(flags
),
558 int WXUNUSED(desiredWidth
),
559 int WXUNUSED(desiredHeight
) )
561 Display
*dpy
= (Display
*) wxGetDisplay();
562 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
564 XpmAttributes xpmAttr
;
568 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
569 xpmAttr
.valuemask
= XpmReturnInfos
| XpmCloseness
;
570 xpmAttr
.closeness
= 40000;
571 int errorStatus
= XpmReadFileToPixmap(dpy
,
572 RootWindow(dpy
, DefaultScreen(dpy
)), (char*) (const char*) name
,
573 &pixmap
, &mask
, &xpmAttr
);
575 if (errorStatus
== XpmSuccess
)
577 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
580 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
581 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
584 unsigned int depthRet
;
586 unsigned int widthRet
, heightRet
, borderWidthRet
;
587 Window rootWindowRet
;
588 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
589 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
591 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
592 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
595 if ( xpmAttr.npixels > 2 )
597 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
600 M_BITMAPHANDLERDATA->m_depth = 1; // mono
604 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
606 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
608 XpmFreeAttributes(&xpmAttr
);
610 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
614 // XpmDebugError(errorStatus, name);
615 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
620 bool wxXPMFileHandler::SaveFile( const wxBitmap
*bitmap
, const wxString
& name
,
621 wxBitmapType
WXUNUSED(type
),
622 const wxPalette
*WXUNUSED(palette
))
624 if (M_BITMAPHANDLERDATA
->m_ok
&& M_BITMAPHANDLERDATA
->m_pixmap
)
626 Display
*dpy
= (Display
*) M_BITMAPHANDLERDATA
->m_display
;
627 int errorStatus
= XpmWriteFileFromPixmap(dpy
, (char*) (const char*) name
,
628 (Pixmap
) M_BITMAPHANDLERDATA
->m_pixmap
,
629 (M_BITMAPHANDLERDATA
->m_bitmapMask
? (Pixmap
) M_BITMAPHANDLERDATA
->m_bitmapMask
->GetPixmap() : (Pixmap
) 0),
630 (XpmAttributes
*) NULL
);
631 if (errorStatus
== XpmSuccess
)
640 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
642 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
644 inline wxXPMDataHandler()
648 m_type
= wxBITMAP_TYPE_XPM_DATA
;
651 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
652 int width
, int height
, int depth
= 1);
654 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
656 bool wxXPMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
657 long WXUNUSED(flags
),
658 int width
, int height
, int WXUNUSED(depth
))
660 M_BITMAPHANDLERDATA
->m_width
= width
;
661 M_BITMAPHANDLERDATA
->m_height
= height
;
662 M_BITMAPHANDLERDATA
->m_depth
= 1;
663 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
665 Display
*dpy
= (Display
*) wxGetDisplay();
666 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
668 XpmAttributes xpmAttr
;
670 xpmAttr
.valuemask
= XpmReturnInfos
; /* nothing yet, but get infos back */
672 XpmColorSymbol symbolicColors
[4];
673 if (sg_Control
&& sg_Control
->GetMainWidget())
675 symbolicColors
[0].name
= "foreground";
676 symbolicColors
[0].value
= NULL
;
677 symbolicColors
[1].name
= "background";
678 symbolicColors
[1].value
= NULL
;
679 XtVaGetValues((Widget
) sg_Control
->GetMainWidget(),
680 XmNforeground
, &symbolicColors
[0].pixel
,
681 XmNbackground
, &symbolicColors
[1].pixel
,NULL
);
682 xpmAttr
.numsymbols
= 2;
683 xpmAttr
.colorsymbols
= symbolicColors
;
684 xpmAttr
.valuemask
|= XpmColorSymbols
; // add flag
689 int ErrorStatus
= XpmCreatePixmapFromData(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)),
690 (char**) data
, &pixmap
, &mask
, &xpmAttr
);
691 if (ErrorStatus
== XpmSuccess
)
694 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
695 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
697 unsigned int depthRet
;
699 unsigned int widthRet
, heightRet
, borderWidthRet
;
700 Window rootWindowRet
;
701 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
702 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
705 if ( xpmAttr.npixels > 2 )
707 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
710 M_BITMAPHANDLERDATA->m_depth = 1; // mono
714 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
716 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
717 XpmFreeAttributes(&xpmAttr
);
718 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
719 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
722 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
723 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
728 // XpmDebugError(ErrorStatus, NULL);
729 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
731 return M_BITMAPHANDLERDATA
->m_ok
;
734 #endif // wxHAVE_LIB_XPM
736 void wxBitmap::InitStandardHandlers()
738 // Initialize all standard bitmap or derived class handlers here.
739 AddHandler(new wxXBMFileHandler
);
740 AddHandler(new wxXBMDataHandler
);
742 // XPM is considered standard for Motif, although it can be omitted if
743 // libXpm is not installed
745 AddHandler(new wxXPMFileHandler
);
746 AddHandler(new wxXPMDataHandler
);
747 #endif // wxHAVE_LIB_XPM
750 WXPixmap
wxBitmap::GetLabelPixmap (WXWidget w
)
753 return (WXPixmap
)NULL
;
754 if (M_BITMAPDATA
->m_image
== (WXPixmap
) 0)
755 return M_BITMAPDATA
->m_pixmap
;
757 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
762 if (labelPixmap) return labelPixmap;
763 things can be wrong, because colors can have been changed.
767 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
768 we got BadDrawable if the pixmap is referenced by multiples widgets
772 So, before doing thing really clean, I just do nothing; if the pixmap is
773 referenced by many widgets, Motif performs caching functions.
774 And if pixmap is referenced with multiples colors, we just have some
775 memory leaks... I hope we can deal with them...
777 // Must be destroyed, because colours can have been changed!
778 if (M_BITMAPDATA
->m_labelPixmap
)
779 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_labelPixmap
);
783 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
786 Widget widget
= (Widget
) w
;
788 while (XmIsGadget ( widget
))
789 widget
= XtParent (widget
);
790 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
792 M_BITMAPDATA
->m_labelPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
794 return M_BITMAPDATA
->m_labelPixmap
;
797 WXPixmap
wxBitmap::GetArmPixmap (WXWidget w
)
799 if (M_BITMAPDATA
->m_image
== (WXPixmap
) 0)
800 return M_BITMAPDATA
->m_pixmap
;
802 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
804 // See GetLabelPixmap () comment
806 // Must be destroyed, because colours can have been changed!
807 if (M_BITMAPDATA
->m_armPixmap
)
808 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_armPixmap
);
812 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
815 Widget widget
= (Widget
) w
;
817 XtVaGetValues (widget
, XmNarmColor
, &bg
, NULL
);
818 while (XmIsGadget (widget
))
819 widget
= XtParent (widget
);
820 XtVaGetValues (widget
, XmNforeground
, &fg
, NULL
);
822 M_BITMAPDATA
->m_armPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
824 return M_BITMAPDATA
->m_armPixmap
;
827 WXPixmap
wxBitmap::GetInsensPixmap (WXWidget w
)
829 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
832 return (WXPixmap
)NULL
;
833 if (M_BITMAPDATA
->m_insensPixmap
)
834 return M_BITMAPDATA
->m_insensPixmap
;
838 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XCreateInsensitivePixmap(dpy
, (Pixmap
) M_BITMAPDATA
->m_pixmap
);
839 if (M_BITMAPDATA
->m_insensPixmap
)
840 return M_BITMAPDATA
->m_insensPixmap
;
842 return M_BITMAPDATA
->m_pixmap
;
845 if (M_BITMAPDATA
->m_insensImage
== (WXPixmap
) 0)
846 return M_BITMAPDATA
->m_pixmap
;
849 See
GetLabelPixmap () comment
850 // Must be destroyed, because colours can have been changed!
851 if (M_BITMAPDATA
->m_insensPixmap
)
852 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), (Pixmap
) M_BITMAPDATA
->m_insensPixmap
);
856 sprintf (tmp
, "Not%x", (unsigned int) M_BITMAPDATA
->m_insensImage
);
859 Widget widget
= (Widget
) w
;
861 while (XmIsGadget (widget
))
862 widget
= XtParent (widget
);
863 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
865 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
867 return M_BITMAPDATA
->m_insensPixmap
;
870 // We may need this sometime...
872 /****************************************************************************
875 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
878 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
881 This function creates a grayed-out copy of the argument pixmap, suitable
882 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
885 The return value is the new Pixmap id or zero on error. Errors include
886 a NULL display argument or an invalid Pixmap argument.
889 If one of the XLib functions fail, it will produce a X error. The
890 default X error handler prints a diagnostic and calls exit().
893 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
894 XFillRectangle(3), exit(2)
897 John R Veregge - john@puente.jpl.nasa.gov
898 Advanced Engineering and Prototyping Group (AEG)
899 Information Systems Technology Section (395)
900 Jet Propulsion Lab - Calif Institute of Technology
902 *****************************************************************************/
905 XCreateInsensitivePixmap( Display
*display
, Pixmap pixmap
)
908 static char stipple_data
[] =
910 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
911 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
912 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
913 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
916 Pixmap ipixmap
, stipple
;
917 unsigned width
, height
, depth
;
919 Window window
; /* These return values */
920 unsigned border
; /* from XGetGeometry() */
921 int x
, y
; /* are not needed. */
925 if ( NULL
== display
|| 0 == pixmap
)
928 if ( 0 == XGetGeometry( display
, pixmap
, &window
, &x
, &y
,
929 &width
, &height
, &border
, &depth
)
931 return ipixmap
; /* BadDrawable: probably an invalid pixmap */
933 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
935 stipple
= XCreateBitmapFromData( display
, pixmap
, stipple_data
, 16, 16 );
938 gc
= XCreateGC( display
, pixmap
, (XtGCMask
)0, (XGCValues
*)NULL
);
941 /* Create an identical copy of the argument pixmap.
943 ipixmap
= XCreatePixmap( display
, pixmap
, width
, height
, depth
);
946 /* Copy the argument pixmap into the new pixmap.
948 XCopyArea( display
, pixmap
, ipixmap
,
949 gc
, 0, 0, width
, height
, 0, 0 );
951 /* Refill the new pixmap using the stipple algorithm/pixmap.
953 XSetStipple( display
, gc
, stipple
);
954 XSetFillStyle( display
, gc
, FillStippled
);
955 XFillRectangle( display
, ipixmap
, gc
, 0, 0, width
, height
);
957 XFreeGC( display
, gc
);
959 XFreePixmap( display
, stipple
);
964 // Creates a bitmap with transparent areas drawn in
966 wxBitmap
wxCreateMaskedBitmap(const wxBitmap
& bitmap
, wxColour
& colour
)
968 wxBitmap
newBitmap(bitmap
.GetWidth(),
973 srcDC
.SelectObject(bitmap
);
974 destDC
.SelectObject(newBitmap
);
976 wxBrush
brush(colour
, wxSOLID
);
977 destDC
.SetOptimization(FALSE
);
978 destDC
.SetBackground(brush
);
980 destDC
.Blit(0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), & srcDC
, 0, 0, wxCOPY
, TRUE
);
988 //-----------------------------------------------------------------------------
989 // wxImage conversion routines
990 //-----------------------------------------------------------------------------
994 Date: Wed, 05 Jan 2000 11:45:40 +0100
995 From: Frits Boel <boel@niob.knaw.nl>
996 To: julian.smart@ukonline.co.uk
997 Subject: Patch for Motif ConvertToBitmap
1001 I've been working on a wxWin application for image processing. From the
1002 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1003 till I looked in the source code of image.cpp. I saw that converting a
1004 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1005 to the 256 colors of the palet. A very time-consuming piece of code!
1007 Because I wanted a faster application, I've made a 'patch' for this. In
1008 short: every pixel of the image is compared to a sorted list with
1009 colors. If the color is found in the list, the palette entry is
1010 returned; if the color is not found, the color palette is searched and
1011 then the palette entry is returned and the color added to the sorted
1014 Maybe there is another method for this, namely changing the palette
1015 itself (if the colors are known, as is the case with tiffs with a
1016 colormap). I did not look at this, maybe someone else did?
1018 The code of the patch is attached, have a look on it, and maybe you will
1019 ship it with the next release of wxMotif?
1024 Software engineer at Hubrecht Laboratory, The Netherlands.
1031 wxSearchColor( void );
1032 wxSearchColor( int size
, XColor
*colors
);
1033 ~wxSearchColor( void );
1035 int SearchColor( int r
, int g
, int b
);
1037 int AddColor( unsigned int value
, int pos
);
1041 unsigned int *color
;
1048 wxSearchColor::wxSearchColor( void )
1051 colors
= (XColor
*) NULL
;
1052 color
= (unsigned int *) NULL
;
1053 entry
= (int*) NULL
;
1059 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
1064 color
= new unsigned int[size
];
1065 entry
= new int [size
];
1067 for (i
= 0; i
< size
; i
++ ) {
1071 bottom
= top
= ( size
>> 1 );
1074 wxSearchColor::~wxSearchColor( void )
1076 if ( color
) delete color
;
1077 if ( entry
) delete entry
;
1080 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1082 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1087 while ( begin
<= end
) {
1089 middle
= ( begin
+ end
) >> 1;
1091 if ( value
== color
[middle
] ) {
1092 return( entry
[middle
] );
1093 } else if ( value
< color
[middle
] ) {
1101 return AddColor( value
, middle
);
1104 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1108 int max
= 3 * (65536);
1109 for ( i
= 0; i
< 256; i
++ ) {
1110 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1111 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1112 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1113 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1114 if (sum
< max
) { pixel
= i
; max
= sum
; }
1117 if ( entry
[pos
] < 0 ) {
1120 } else if ( value
< color
[pos
] ) {
1123 for ( i
= bottom
; i
< pos
; i
++ ) {
1124 color
[i
-1] = color
[i
];
1125 entry
[i
-1] = entry
[i
];
1128 color
[pos
-1] = value
;
1129 entry
[pos
-1] = pixel
;
1130 } else if ( top
< size
-1 ) {
1131 for ( i
= top
; i
>= pos
; i
-- ) {
1132 color
[i
+1] = color
[i
];
1133 entry
[i
+1] = entry
[i
];
1142 if ( top
< size
-1 ) {
1143 for ( i
= top
; i
> pos
; i
-- ) {
1144 color
[i
+1] = color
[i
];
1145 entry
[i
+1] = entry
[i
];
1148 color
[pos
+1] = value
;
1149 entry
[pos
+1] = pixel
;
1150 } else if ( bottom
> 0 ) {
1151 for ( i
= bottom
; i
< pos
; i
++ ) {
1152 color
[i
-1] = color
[i
];
1153 entry
[i
-1] = entry
[i
];
1166 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
1168 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
1169 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
1171 m_refData
= new wxBitmapRefData();
1173 int width
= image
.GetWidth();
1174 int height
= image
.GetHeight();
1176 SetHeight( height
);
1179 Display
*dpy
= (Display
*) wxGetDisplay();
1180 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1181 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1185 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1186 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1188 Create( width
, height
, bpp
);
1192 XImage
*mask_image
= (XImage
*) NULL
;
1193 if (image
.HasMask())
1195 mask_image
= XCreateImage( dpy
, vis
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1196 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
1199 // Retrieve depth info
1201 XVisualInfo vinfo_template
;
1204 vinfo_template
.visual
= vis
;
1205 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1206 vinfo_template
.depth
= bpp
;
1209 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1211 wxCHECK_MSG( vi
, FALSE
, wxT("no visual") );
1215 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1216 if (bpp
< 8) bpp
= 8;
1220 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1221 byte_order b_o
= RGB
;
1225 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1226 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1227 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1228 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1229 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1230 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1233 int r_mask
= image
.GetMaskRed();
1234 int g_mask
= image
.GetMaskGreen();
1235 int b_mask
= image
.GetMaskBlue();
1240 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1242 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1243 XQueryColors( dpy
, cmap
, colors
, 256 );
1246 wxSearchColor
scolor( 256, colors
);
1247 unsigned char* data
= image
.GetData();
1249 bool hasMask
= image
.HasMask();
1252 for (int y
= 0; y
< height
; y
++)
1254 for (int x
= 0; x
< width
; x
++)
1256 int r
= data
[index
];
1258 int g
= data
[index
];
1260 int b
= data
[index
];
1265 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1266 XPutPixel( mask_image
, x
, y
, 0 );
1268 XPutPixel( mask_image
, x
, y
, 1 );
1275 #if 0 // Old, slower code
1278 if (wxTheApp->m_colorCube)
1280 pixel = wxTheApp->m_colorCube
1281 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1286 int max
= 3 * (65536);
1287 for (int i
= 0; i
< 256; i
++)
1289 int rdiff
= (r
<< 8) - colors
[i
].red
;
1290 int gdiff
= (g
<< 8) - colors
[i
].green
;
1291 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1292 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1293 if (sum
< max
) { pixel
= i
; max
= sum
; }
1300 // And this is all to get the 'right' color...
1301 int pixel
= scolor
.SearchColor( r
, g
, b
);
1302 XPutPixel( data_image
, x
, y
, pixel
);
1307 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1308 XPutPixel( data_image
, x
, y
, pixel
);
1313 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1314 XPutPixel( data_image
, x
, y
, pixel
);
1323 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1324 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1325 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1326 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1327 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1328 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1330 XPutPixel( data_image
, x
, y
, pixel
);
1340 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1341 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1342 XPutImage( dpy
, (Drawable
)GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1344 XDestroyImage( data_image
);
1348 if (image
.HasMask())
1350 wxBitmap
maskBitmap(width
, height
, 1);
1352 GC gcMask
= XCreateGC( dpy
, (Pixmap
) maskBitmap
.GetPixmap(), (XtGCMask
) 0, (XGCValues
*)NULL
);
1353 XPutImage( dpy
, (Drawable
)maskBitmap
.GetPixmap(), gcMask
, mask_image
, 0, 0, 0, 0, width
, height
);
1355 XDestroyImage( mask_image
);
1356 XFreeGC( dpy
, gcMask
);
1358 wxMask
* mask
= new wxMask
;
1359 mask
->SetPixmap(maskBitmap
.GetPixmap());
1363 maskBitmap
.SetPixmapNull();
1370 wxImage
wxBitmap::ConvertToImage() const
1374 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
1376 Display
*dpy
= (Display
*) wxGetDisplay();
1377 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1378 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1380 XImage
*ximage
= XGetImage( dpy
,
1381 (Drawable
)GetPixmap(),
1383 GetWidth(), GetHeight(),
1384 AllPlanes
, ZPixmap
);
1386 wxCHECK_MSG( ximage
, wxNullImage
, wxT("couldn't create image") );
1388 image
.Create( GetWidth(), GetHeight() );
1389 char unsigned *data
= image
.GetData();
1393 XDestroyImage( ximage
);
1394 wxFAIL_MSG( wxT("couldn't create image") );
1399 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1402 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1404 GetWidth(), GetHeight() );
1406 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1410 // Retrieve depth info
1412 XVisualInfo vinfo_template
;
1415 vinfo_template
.visual
= vis
;
1416 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1417 vinfo_template
.depth
= bpp
;
1420 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1422 wxCHECK_MSG( vi
, wxNullImage
, wxT("no visual") );
1424 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1431 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1433 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1434 XQueryColors( dpy
, cmap
, colors
, 256 );
1438 for (int j
= 0; j
< GetHeight(); j
++)
1440 for (int i
= 0; i
< GetWidth(); i
++)
1442 int pixel
= XGetPixel( ximage
, i
, j
);
1445 data
[pos
] = colors
[pixel
].red
>> 8;
1446 data
[pos
+1] = colors
[pixel
].green
>> 8;
1447 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1448 } else if (bpp
== 15)
1450 data
[pos
] = (pixel
>> 7) & 0xf8;
1451 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1452 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1453 } else if (bpp
== 16)
1455 data
[pos
] = (pixel
>> 8) & 0xf8;
1456 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1457 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1460 data
[pos
] = (pixel
>> 16) & 0xff;
1461 data
[pos
+1] = (pixel
>> 8) & 0xff;
1462 data
[pos
+2] = pixel
& 0xff;
1468 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1469 if (mask_pixel == 0)
1482 XDestroyImage( ximage
);
1484 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );