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 wxConstCast(name
.c_str(), char), &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
)),
573 wxConstCast(name
.c_str(), char),
574 &pixmap
, &mask
, &xpmAttr
);
576 if (errorStatus
== XpmSuccess
)
578 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
581 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
582 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
585 unsigned int depthRet
;
587 unsigned int widthRet
, heightRet
, borderWidthRet
;
588 Window rootWindowRet
;
589 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
590 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
592 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
593 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
596 if ( xpmAttr.npixels > 2 )
598 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
601 M_BITMAPHANDLERDATA->m_depth = 1; // mono
605 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
607 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
609 XpmFreeAttributes(&xpmAttr
);
611 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
615 // XpmDebugError(errorStatus, name);
616 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
621 bool wxXPMFileHandler::SaveFile( const wxBitmap
*bitmap
, const wxString
& name
,
622 wxBitmapType
WXUNUSED(type
),
623 const wxPalette
*WXUNUSED(palette
))
625 if (M_BITMAPHANDLERDATA
->m_ok
&& M_BITMAPHANDLERDATA
->m_pixmap
)
627 Display
*dpy
= (Display
*) M_BITMAPHANDLERDATA
->m_display
;
628 int errorStatus
= XpmWriteFileFromPixmap(dpy
,
629 wxConstCast(name
.c_str(), char),
630 (Pixmap
) M_BITMAPHANDLERDATA
->m_pixmap
,
631 (M_BITMAPHANDLERDATA
->m_bitmapMask
? (Pixmap
) M_BITMAPHANDLERDATA
->m_bitmapMask
->GetPixmap() : (Pixmap
) 0),
632 (XpmAttributes
*) NULL
);
633 if (errorStatus
== XpmSuccess
)
642 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
644 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
646 inline wxXPMDataHandler()
650 m_type
= wxBITMAP_TYPE_XPM_DATA
;
653 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
654 int width
, int height
, int depth
= 1);
656 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
658 bool wxXPMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
659 long WXUNUSED(flags
),
660 int width
, int height
, int WXUNUSED(depth
))
662 M_BITMAPHANDLERDATA
->m_width
= width
;
663 M_BITMAPHANDLERDATA
->m_height
= height
;
664 M_BITMAPHANDLERDATA
->m_depth
= 1;
665 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
667 Display
*dpy
= (Display
*) wxGetDisplay();
668 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
670 XpmAttributes xpmAttr
;
672 xpmAttr
.valuemask
= XpmReturnInfos
; /* nothing yet, but get infos back */
674 XpmColorSymbol symbolicColors
[4];
675 if (sg_Control
&& sg_Control
->GetMainWidget())
677 symbolicColors
[0].name
= "foreground";
678 symbolicColors
[0].value
= NULL
;
679 symbolicColors
[1].name
= "background";
680 symbolicColors
[1].value
= NULL
;
681 XtVaGetValues((Widget
) sg_Control
->GetMainWidget(),
682 XmNforeground
, &symbolicColors
[0].pixel
,
683 XmNbackground
, &symbolicColors
[1].pixel
,NULL
);
684 xpmAttr
.numsymbols
= 2;
685 xpmAttr
.colorsymbols
= symbolicColors
;
686 xpmAttr
.valuemask
|= XpmColorSymbols
; // add flag
691 int ErrorStatus
= XpmCreatePixmapFromData(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)),
692 (char**) data
, &pixmap
, &mask
, &xpmAttr
);
693 if (ErrorStatus
== XpmSuccess
)
696 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
697 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
699 unsigned int depthRet
;
701 unsigned int widthRet
, heightRet
, borderWidthRet
;
702 Window rootWindowRet
;
703 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
704 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
707 if ( xpmAttr.npixels > 2 )
709 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
712 M_BITMAPHANDLERDATA->m_depth = 1; // mono
716 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
718 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
719 XpmFreeAttributes(&xpmAttr
);
720 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
721 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
724 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
725 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
730 // XpmDebugError(ErrorStatus, NULL);
731 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
733 return M_BITMAPHANDLERDATA
->m_ok
;
736 #endif // wxHAVE_LIB_XPM
738 void wxBitmap::InitStandardHandlers()
740 // Initialize all standard bitmap or derived class handlers here.
741 AddHandler(new wxXBMFileHandler
);
742 AddHandler(new wxXBMDataHandler
);
744 // XPM is considered standard for Motif, although it can be omitted if
745 // libXpm is not installed
747 AddHandler(new wxXPMFileHandler
);
748 AddHandler(new wxXPMDataHandler
);
749 #endif // wxHAVE_LIB_XPM
752 WXPixmap
wxBitmap::GetLabelPixmap (WXWidget w
)
755 return (WXPixmap
)NULL
;
756 if (M_BITMAPDATA
->m_image
== (WXPixmap
) 0)
757 return M_BITMAPDATA
->m_pixmap
;
759 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
764 if (labelPixmap) return labelPixmap;
765 things can be wrong, because colors can have been changed.
769 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
770 we got BadDrawable if the pixmap is referenced by multiples widgets
774 So, before doing thing really clean, I just do nothing; if the pixmap is
775 referenced by many widgets, Motif performs caching functions.
776 And if pixmap is referenced with multiples colors, we just have some
777 memory leaks... I hope we can deal with them...
779 // Must be destroyed, because colours can have been changed!
780 if (M_BITMAPDATA
->m_labelPixmap
)
781 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_labelPixmap
);
785 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
788 Widget widget
= (Widget
) w
;
790 while (XmIsGadget ( widget
))
791 widget
= XtParent (widget
);
792 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
794 M_BITMAPDATA
->m_labelPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
796 return M_BITMAPDATA
->m_labelPixmap
;
799 WXPixmap
wxBitmap::GetArmPixmap (WXWidget w
)
801 if (M_BITMAPDATA
->m_image
== (WXPixmap
) 0)
802 return M_BITMAPDATA
->m_pixmap
;
804 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
806 // See GetLabelPixmap () comment
808 // Must be destroyed, because colours can have been changed!
809 if (M_BITMAPDATA
->m_armPixmap
)
810 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_armPixmap
);
814 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
817 Widget widget
= (Widget
) w
;
819 XtVaGetValues (widget
, XmNarmColor
, &bg
, NULL
);
820 while (XmIsGadget (widget
))
821 widget
= XtParent (widget
);
822 XtVaGetValues (widget
, XmNforeground
, &fg
, NULL
);
824 M_BITMAPDATA
->m_armPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
826 return M_BITMAPDATA
->m_armPixmap
;
829 WXPixmap
wxBitmap::GetInsensPixmap (WXWidget w
)
831 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
834 return (WXPixmap
)NULL
;
835 if (M_BITMAPDATA
->m_insensPixmap
)
836 return M_BITMAPDATA
->m_insensPixmap
;
840 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XCreateInsensitivePixmap(dpy
, (Pixmap
) M_BITMAPDATA
->m_pixmap
);
841 if (M_BITMAPDATA
->m_insensPixmap
)
842 return M_BITMAPDATA
->m_insensPixmap
;
844 return M_BITMAPDATA
->m_pixmap
;
847 if (M_BITMAPDATA
->m_insensImage
== (WXPixmap
) 0)
848 return M_BITMAPDATA
->m_pixmap
;
851 See
GetLabelPixmap () comment
852 // Must be destroyed, because colours can have been changed!
853 if (M_BITMAPDATA
->m_insensPixmap
)
854 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), (Pixmap
) M_BITMAPDATA
->m_insensPixmap
);
858 sprintf (tmp
, "Not%x", (unsigned int) M_BITMAPDATA
->m_insensImage
);
861 Widget widget
= (Widget
) w
;
863 while (XmIsGadget (widget
))
864 widget
= XtParent (widget
);
865 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
867 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
869 return M_BITMAPDATA
->m_insensPixmap
;
872 // We may need this sometime...
874 /****************************************************************************
877 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
880 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
883 This function creates a grayed-out copy of the argument pixmap, suitable
884 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
887 The return value is the new Pixmap id or zero on error. Errors include
888 a NULL display argument or an invalid Pixmap argument.
891 If one of the XLib functions fail, it will produce a X error. The
892 default X error handler prints a diagnostic and calls exit().
895 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
896 XFillRectangle(3), exit(2)
899 John R Veregge - john@puente.jpl.nasa.gov
900 Advanced Engineering and Prototyping Group (AEG)
901 Information Systems Technology Section (395)
902 Jet Propulsion Lab - Calif Institute of Technology
904 *****************************************************************************/
907 XCreateInsensitivePixmap( Display
*display
, Pixmap pixmap
)
910 static char stipple_data
[] =
912 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
913 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
914 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
915 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
918 Pixmap ipixmap
, stipple
;
919 unsigned width
, height
, depth
;
921 Window window
; /* These return values */
922 unsigned border
; /* from XGetGeometry() */
923 int x
, y
; /* are not needed. */
927 if ( NULL
== display
|| 0 == pixmap
)
930 if ( 0 == XGetGeometry( display
, pixmap
, &window
, &x
, &y
,
931 &width
, &height
, &border
, &depth
)
933 return ipixmap
; /* BadDrawable: probably an invalid pixmap */
935 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
937 stipple
= XCreateBitmapFromData( display
, pixmap
, stipple_data
, 16, 16 );
940 gc
= XCreateGC( display
, pixmap
, (XtGCMask
)0, (XGCValues
*)NULL
);
943 /* Create an identical copy of the argument pixmap.
945 ipixmap
= XCreatePixmap( display
, pixmap
, width
, height
, depth
);
948 /* Copy the argument pixmap into the new pixmap.
950 XCopyArea( display
, pixmap
, ipixmap
,
951 gc
, 0, 0, width
, height
, 0, 0 );
953 /* Refill the new pixmap using the stipple algorithm/pixmap.
955 XSetStipple( display
, gc
, stipple
);
956 XSetFillStyle( display
, gc
, FillStippled
);
957 XFillRectangle( display
, ipixmap
, gc
, 0, 0, width
, height
);
959 XFreeGC( display
, gc
);
961 XFreePixmap( display
, stipple
);
966 // Creates a bitmap with transparent areas drawn in
968 wxBitmap
wxCreateMaskedBitmap(const wxBitmap
& bitmap
, wxColour
& colour
)
970 wxBitmap
newBitmap(bitmap
.GetWidth(),
975 srcDC
.SelectObject(bitmap
);
976 destDC
.SelectObject(newBitmap
);
978 wxBrush
brush(colour
, wxSOLID
);
979 destDC
.SetOptimization(FALSE
);
980 destDC
.SetBackground(brush
);
982 destDC
.Blit(0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), & srcDC
, 0, 0, wxCOPY
, TRUE
);
990 //-----------------------------------------------------------------------------
991 // wxImage conversion routines
992 //-----------------------------------------------------------------------------
996 Date: Wed, 05 Jan 2000 11:45:40 +0100
997 From: Frits Boel <boel@niob.knaw.nl>
998 To: julian.smart@ukonline.co.uk
999 Subject: Patch for Motif ConvertToBitmap
1003 I've been working on a wxWin application for image processing. From the
1004 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1005 till I looked in the source code of image.cpp. I saw that converting a
1006 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1007 to the 256 colors of the palet. A very time-consuming piece of code!
1009 Because I wanted a faster application, I've made a 'patch' for this. In
1010 short: every pixel of the image is compared to a sorted list with
1011 colors. If the color is found in the list, the palette entry is
1012 returned; if the color is not found, the color palette is searched and
1013 then the palette entry is returned and the color added to the sorted
1016 Maybe there is another method for this, namely changing the palette
1017 itself (if the colors are known, as is the case with tiffs with a
1018 colormap). I did not look at this, maybe someone else did?
1020 The code of the patch is attached, have a look on it, and maybe you will
1021 ship it with the next release of wxMotif?
1026 Software engineer at Hubrecht Laboratory, The Netherlands.
1033 wxSearchColor( void );
1034 wxSearchColor( int size
, XColor
*colors
);
1035 ~wxSearchColor( void );
1037 int SearchColor( int r
, int g
, int b
);
1039 int AddColor( unsigned int value
, int pos
);
1043 unsigned int *color
;
1050 wxSearchColor::wxSearchColor( void )
1053 colors
= (XColor
*) NULL
;
1054 color
= (unsigned int *) NULL
;
1055 entry
= (int*) NULL
;
1061 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
1066 color
= new unsigned int[size
];
1067 entry
= new int [size
];
1069 for (i
= 0; i
< size
; i
++ ) {
1073 bottom
= top
= ( size
>> 1 );
1076 wxSearchColor::~wxSearchColor( void )
1078 if ( color
) delete color
;
1079 if ( entry
) delete entry
;
1082 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1084 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1089 while ( begin
<= end
) {
1091 middle
= ( begin
+ end
) >> 1;
1093 if ( value
== color
[middle
] ) {
1094 return( entry
[middle
] );
1095 } else if ( value
< color
[middle
] ) {
1103 return AddColor( value
, middle
);
1106 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1110 int max
= 3 * (65536);
1111 for ( i
= 0; i
< 256; i
++ ) {
1112 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1113 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1114 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1115 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1116 if (sum
< max
) { pixel
= i
; max
= sum
; }
1119 if ( entry
[pos
] < 0 ) {
1122 } else if ( value
< color
[pos
] ) {
1125 for ( i
= bottom
; i
< pos
; i
++ ) {
1126 color
[i
-1] = color
[i
];
1127 entry
[i
-1] = entry
[i
];
1130 color
[pos
-1] = value
;
1131 entry
[pos
-1] = pixel
;
1132 } else if ( top
< size
-1 ) {
1133 for ( i
= top
; i
>= pos
; i
-- ) {
1134 color
[i
+1] = color
[i
];
1135 entry
[i
+1] = entry
[i
];
1144 if ( top
< size
-1 ) {
1145 for ( i
= top
; i
> pos
; i
-- ) {
1146 color
[i
+1] = color
[i
];
1147 entry
[i
+1] = entry
[i
];
1150 color
[pos
+1] = value
;
1151 entry
[pos
+1] = pixel
;
1152 } else if ( bottom
> 0 ) {
1153 for ( i
= bottom
; i
< pos
; i
++ ) {
1154 color
[i
-1] = color
[i
];
1155 entry
[i
-1] = entry
[i
];
1168 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
1170 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
1171 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
1173 m_refData
= new wxBitmapRefData();
1175 int width
= image
.GetWidth();
1176 int height
= image
.GetHeight();
1178 SetHeight( height
);
1181 Display
*dpy
= (Display
*) wxGetDisplay();
1182 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1183 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1187 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1188 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1190 Create( width
, height
, bpp
);
1194 XImage
*mask_image
= (XImage
*) NULL
;
1195 if (image
.HasMask())
1197 mask_image
= XCreateImage( dpy
, vis
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1198 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
1201 // Retrieve depth info
1203 XVisualInfo vinfo_template
;
1206 vinfo_template
.visual
= vis
;
1207 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1208 vinfo_template
.depth
= bpp
;
1211 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1213 wxCHECK_MSG( vi
, FALSE
, wxT("no visual") );
1217 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1218 if (bpp
< 8) bpp
= 8;
1222 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1223 byte_order b_o
= RGB
;
1227 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1228 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1229 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1230 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1231 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1232 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1235 int r_mask
= image
.GetMaskRed();
1236 int g_mask
= image
.GetMaskGreen();
1237 int b_mask
= image
.GetMaskBlue();
1242 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1244 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1245 XQueryColors( dpy
, cmap
, colors
, 256 );
1248 wxSearchColor
scolor( 256, colors
);
1249 unsigned char* data
= image
.GetData();
1251 bool hasMask
= image
.HasMask();
1254 for (int y
= 0; y
< height
; y
++)
1256 for (int x
= 0; x
< width
; x
++)
1258 int r
= data
[index
];
1260 int g
= data
[index
];
1262 int b
= data
[index
];
1267 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1268 XPutPixel( mask_image
, x
, y
, 0 );
1270 XPutPixel( mask_image
, x
, y
, 1 );
1277 #if 0 // Old, slower code
1280 if (wxTheApp->m_colorCube)
1282 pixel = wxTheApp->m_colorCube
1283 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1288 int max
= 3 * (65536);
1289 for (int i
= 0; i
< 256; i
++)
1291 int rdiff
= (r
<< 8) - colors
[i
].red
;
1292 int gdiff
= (g
<< 8) - colors
[i
].green
;
1293 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1294 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1295 if (sum
< max
) { pixel
= i
; max
= sum
; }
1302 // And this is all to get the 'right' color...
1303 int pixel
= scolor
.SearchColor( r
, g
, b
);
1304 XPutPixel( data_image
, x
, y
, pixel
);
1309 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1310 XPutPixel( data_image
, x
, y
, pixel
);
1315 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1316 XPutPixel( data_image
, x
, y
, pixel
);
1325 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1326 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1327 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1328 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1329 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1330 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1332 XPutPixel( data_image
, x
, y
, pixel
);
1342 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1343 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1344 XPutImage( dpy
, (Drawable
)GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1346 XDestroyImage( data_image
);
1350 if (image
.HasMask())
1352 wxBitmap
maskBitmap(width
, height
, 1);
1354 GC gcMask
= XCreateGC( dpy
, (Pixmap
) maskBitmap
.GetPixmap(), (XtGCMask
) 0, (XGCValues
*)NULL
);
1355 XPutImage( dpy
, (Drawable
)maskBitmap
.GetPixmap(), gcMask
, mask_image
, 0, 0, 0, 0, width
, height
);
1357 XDestroyImage( mask_image
);
1358 XFreeGC( dpy
, gcMask
);
1360 wxMask
* mask
= new wxMask
;
1361 mask
->SetPixmap(maskBitmap
.GetPixmap());
1365 maskBitmap
.SetPixmapNull();
1372 wxImage
wxBitmap::ConvertToImage() const
1376 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
1378 Display
*dpy
= (Display
*) wxGetDisplay();
1379 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1380 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1382 XImage
*ximage
= XGetImage( dpy
,
1383 (Drawable
)GetPixmap(),
1385 GetWidth(), GetHeight(),
1386 AllPlanes
, ZPixmap
);
1388 wxCHECK_MSG( ximage
, wxNullImage
, wxT("couldn't create image") );
1390 image
.Create( GetWidth(), GetHeight() );
1391 char unsigned *data
= image
.GetData();
1395 XDestroyImage( ximage
);
1396 wxFAIL_MSG( wxT("couldn't create image") );
1401 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1404 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1406 GetWidth(), GetHeight() );
1408 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1412 // Retrieve depth info
1414 XVisualInfo vinfo_template
;
1417 vinfo_template
.visual
= vis
;
1418 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1419 vinfo_template
.depth
= bpp
;
1422 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1424 wxCHECK_MSG( vi
, wxNullImage
, wxT("no visual") );
1426 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1433 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1435 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1436 XQueryColors( dpy
, cmap
, colors
, 256 );
1440 for (int j
= 0; j
< GetHeight(); j
++)
1442 for (int i
= 0; i
< GetWidth(); i
++)
1444 int pixel
= XGetPixel( ximage
, i
, j
);
1447 data
[pos
] = colors
[pixel
].red
>> 8;
1448 data
[pos
+1] = colors
[pixel
].green
>> 8;
1449 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1450 } else if (bpp
== 15)
1452 data
[pos
] = (pixel
>> 7) & 0xf8;
1453 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1454 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1455 } else if (bpp
== 16)
1457 data
[pos
] = (pixel
>> 8) & 0xf8;
1458 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1459 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1462 data
[pos
] = (pixel
>> 16) & 0xff;
1463 data
[pos
+1] = (pixel
>> 8) & 0xff;
1464 data
[pos
+2] = pixel
& 0xff;
1470 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1471 if (mask_pixel == 0)
1484 XDestroyImage( ximage
);
1486 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );