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?
65 m_freeColors
= (unsigned long*) 0;
66 m_freeColorsCount
= 0;
69 // These 5 variables are for wxControl
71 m_insensPixmap
= (WXPixmap
) 0;
72 m_labelPixmap
= (WXPixmap
) 0;
73 m_armPixmap
= (WXPixmap
) 0;
76 m_image
= (WXImage
*) 0;
77 m_insensImage
= (WXImage
*) 0;
81 wxBitmapRefData::~wxBitmapRefData()
85 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_labelPixmap
);
88 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_armPixmap
);
91 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_insensPixmap
);
97 XmUninstallImage ((XImage
*) m_image
);
98 XtFree ((char *) (XImage
*) m_image
);
105 XmUninstallImage ((XImage
*) m_insensImage
);
106 delete[] ((XImage
*) m_insensImage
)->data
;
107 XtFree ((char *) (XImage
*) m_insensImage
);
110 if (m_pixmap
/* && m_freePixmap */)
111 XFreePixmap ((Display
*) m_display
, (Pixmap
) m_pixmap
);
116 int screen
= DefaultScreen((Display
*) m_display
);
117 Colormap cmp
= DefaultColormap((Display
*) m_display
,screen
);
119 for(llp
= 0;llp
< m_freeColorsCount
;llp
++)
120 XFreeColors((Display
*) m_display
, cmp
, &m_freeColors
[llp
], 1, 0L);
130 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
137 wxBitmap::~wxBitmap()
141 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
143 m_refData
= new wxBitmapRefData
;
145 (void) Create((void*) bits
, wxBITMAP_TYPE_XBM_DATA
, width
, height
, depth
);
148 wxBitmap::wxBitmap(int w
, int h
, int d
)
150 (void)Create(w
, h
, d
);
153 wxBitmap::wxBitmap(void *data
, wxBitmapType type
,
154 int width
, int height
, int depth
)
156 (void) Create(data
, type
, width
, height
, depth
);
159 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
)
161 LoadFile(filename
, type
);
164 // Create from XPM data
165 static wxControl
* sg_Control
= NULL
;
166 wxBitmap::wxBitmap(char **data
, wxControl
* control
)
168 // Pass the control to the Create function using a global
169 sg_Control
= control
;
171 (void) Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
173 sg_Control
= (wxControl
*) NULL
;
176 bool wxBitmap::CreateFromXpm(const char **bits
)
178 wxCHECK_MSG( bits
, FALSE
, _T("NULL pointer in wxBitmap::CreateFromXpm") );
180 return Create(bits
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
183 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
189 bool wxBitmap::Create(int w
, int h
, int d
)
193 m_refData
= new wxBitmapRefData
;
196 d
= wxDisplayDepth();
198 M_BITMAPDATA
->m_width
= w
;
199 M_BITMAPDATA
->m_height
= h
;
200 M_BITMAPDATA
->m_depth
= d
;
201 // M_BITMAPDATA->m_freePixmap = TRUE;
203 Display
*dpy
= (Display
*) wxGetDisplay();
205 M_BITMAPDATA
->m_display
= dpy
; /* MATTHEW: [4] Remember the display */
207 M_BITMAPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
210 M_BITMAPDATA
->m_ok
= (M_BITMAPDATA
->m_pixmap
!= (WXPixmap
) 0) ;
211 return M_BITMAPDATA
->m_ok
;
214 bool wxBitmap::LoadFile(const wxString
& filename
, wxBitmapType type
)
218 m_refData
= new wxBitmapRefData
;
220 wxBitmapHandler
*handler
= FindHandler(type
);
222 if ( handler
== NULL
) {
224 if (!image
.LoadFile( filename
, type
)) return FALSE
;
227 *this = wxBitmap(image
);
233 return handler
->LoadFile(this, filename
, type
, -1, -1);
236 bool wxBitmap::Create(void *data
, wxBitmapType type
,
237 int width
, int height
, int depth
)
241 m_refData
= new wxBitmapRefData
;
243 wxBitmapHandler
*handler
= FindHandler(type
);
245 if ( handler
== NULL
) {
246 wxLogWarning("no data bitmap handler for type %ld defined.",
252 return handler
->Create(this, data
, type
, width
, height
, depth
);
255 bool wxBitmap::SaveFile(const wxString
& filename
, wxBitmapType type
,
256 const wxPalette
*palette
) const
258 wxBitmapHandler
*handler
= FindHandler(type
);
260 if ( handler
== NULL
) { // try wxImage
261 wxImage image
= this->ConvertToImage();
262 if (image
.Ok()) return image
.SaveFile( filename
, type
);
266 return handler
->SaveFile(this, filename
, type
, palette
);
269 void wxBitmap::SetWidth(int w
)
272 m_refData
= new wxBitmapRefData
;
274 M_BITMAPDATA
->m_width
= w
;
277 void wxBitmap::SetHeight(int h
)
280 m_refData
= new wxBitmapRefData
;
282 M_BITMAPDATA
->m_height
= h
;
285 void wxBitmap::SetDepth(int d
)
288 m_refData
= new wxBitmapRefData
;
290 M_BITMAPDATA
->m_depth
= d
;
296 void wxBitmap::SetQuality(int q
)
299 m_refData
= new wxBitmapRefData
;
301 M_BITMAPDATA
->m_quality
= q
;
306 void wxBitmap::SetOk(bool isOk
)
309 m_refData
= new wxBitmapRefData
;
311 M_BITMAPDATA
->m_ok
= isOk
;
314 void wxBitmap::SetPalette(const wxPalette
& palette
)
317 m_refData
= new wxBitmapRefData
;
319 M_BITMAPDATA
->m_bitmapPalette
= palette
;
322 void wxBitmap::SetMask(wxMask
*mask
)
325 m_refData
= new wxBitmapRefData
;
327 M_BITMAPDATA
->m_bitmapMask
= mask
;
330 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
333 (rect
.x
>= 0) && (rect
.y
>= 0) &&
334 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) && (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
335 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
337 wxBitmap
ret( rect
.width
, rect
.height
, 0 );
338 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
340 // The remaining still TODO
350 m_pixmap
= (WXPixmap
) 0;
353 // Construct a mask from a bitmap and a colour indicating
354 // the transparent area
355 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
357 m_pixmap
= (WXPixmap
) 0;
359 Create(bitmap
, colour
);
362 // Construct a mask from a bitmap and a palette index indicating
363 // the transparent area
364 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
366 m_pixmap
= (WXPixmap
) 0;
368 Create(bitmap
, paletteIndex
);
371 // Construct a mask from a mono bitmap (copies the bitmap).
372 wxMask::wxMask(const wxBitmap
& bitmap
)
374 m_pixmap
= (WXPixmap
) 0;
381 // TODO: this may be the wrong display
383 XFreePixmap ((Display
*) wxGetDisplay(), (Pixmap
) m_pixmap
);
386 // Create a mask from a mono bitmap (copies the bitmap).
387 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
))
393 // Create a mask from a bitmap and a palette index indicating
394 // the transparent area
395 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), int WXUNUSED(paletteIndex
))
401 // Create a mask from a bitmap and a colour indicating
402 // the transparent area
403 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), const wxColour
& WXUNUSED(colour
))
413 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
419 class WXDLLEXPORT wxXBMFileHandler
: public wxBitmapHandler
421 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler
)
423 inline wxXBMFileHandler()
427 m_type
= wxBITMAP_TYPE_XBM
;
430 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
431 int desiredWidth
, int desiredHeight
);
434 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler
, wxBitmapHandler
)
436 bool wxXBMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
,
437 long WXUNUSED(flags
),
438 int WXUNUSED(desiredWidth
),
439 int WXUNUSED(desiredHeight
))
441 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
447 Display
*dpy
= (Display
*) wxGetDisplay();
448 M_BITMAPDATA
->m_display
= (WXDisplay
*) dpy
;
450 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
451 wxConstCast(name
.c_str(), char), &w
, &h
, &pixmap
, &hotX
, &hotY
);
452 M_BITMAPHANDLERDATA
->m_width
= w
;
453 M_BITMAPHANDLERDATA
->m_height
= h
;
454 M_BITMAPHANDLERDATA
->m_depth
= 1;
455 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
457 if ((value
== BitmapFileInvalid
) ||
458 (value
== BitmapOpenFailed
) ||
459 (value
== BitmapNoMemory
))
461 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
462 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) 0;
465 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
467 return M_BITMAPHANDLERDATA
->m_ok
;
470 class WXDLLEXPORT wxXBMDataHandler
: public wxBitmapHandler
472 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler
)
474 inline wxXBMDataHandler()
478 m_type
= wxBITMAP_TYPE_XBM_DATA
;
481 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
482 int width
, int height
, int depth
= 1);
484 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler
, wxBitmapHandler
)
486 bool wxXBMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
487 long WXUNUSED(flags
),
488 int width
, int height
, int WXUNUSED(depth
))
490 M_BITMAPHANDLERDATA
->m_width
= width
;
491 M_BITMAPHANDLERDATA
->m_height
= height
;
492 M_BITMAPHANDLERDATA
->m_depth
= 1;
493 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
495 Display
*dpy
= (Display
*) wxGetDisplay();
496 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
498 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) XCreateBitmapFromData (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)), (char*) data
, width
, height
);
499 M_BITMAPHANDLERDATA
->m_ok
= (M_BITMAPHANDLERDATA
->m_pixmap
!= (WXPixmap
) 0) ;
502 // code for wxControl. TODO: can we avoid doing this until we need it?
503 // E.g. have CreateButtonPixmaps which is called on demand.
504 XImage
* image
= (XImage
*) XtMalloc (sizeof (XImage
));
505 image
->width
= width
;
506 image
->height
= height
;
507 image
->data
= (char*) data
;
510 image
->format
= XYBitmap
;
511 image
->byte_order
= LSBFirst
;
512 image
->bitmap_unit
= 8;
513 image
->bitmap_bit_order
= LSBFirst
;
514 image
->bitmap_pad
= 8;
515 image
->bytes_per_line
= (width
+ 7) >> 3;
518 sprintf (tmp
, "Im%x", (unsigned int) image
);
519 XmInstallImage (image
, tmp
);
521 // Build our manually stipped pixmap.
523 int bpl
= (width
+ 7) / 8;
524 char *data1
= new char[height
* bpl
];
525 char* bits
= (char*) data
;
527 for (i
= 0; i
< height
; i
++)
529 int mask
= i
% 2 ? 0x55 : 0xaa;
531 for (j
= 0; j
< bpl
; j
++)
532 data1
[i
* bpl
+ j
] = bits
[i
* bpl
+ j
] & mask
;
534 XImage
* insensImage
= (XImage
*) XtMalloc (sizeof (XImage
));
535 insensImage
->width
= width
;
536 insensImage
->height
= height
;
537 insensImage
->data
= data1
;
538 insensImage
->depth
= 1;
539 insensImage
->xoffset
= 0;
540 insensImage
->format
= XYBitmap
;
541 insensImage
->byte_order
= LSBFirst
;
542 insensImage
->bitmap_unit
= 8;
543 insensImage
->bitmap_bit_order
= LSBFirst
;
544 insensImage
->bitmap_pad
= 8;
545 insensImage
->bytes_per_line
= bpl
;
547 sprintf (tmp
, "Not%x", (unsigned int)insensImage
);
548 XmInstallImage (insensImage
, tmp
);
550 M_BITMAPHANDLERDATA
->m_image
= (WXImage
*) image
;
551 M_BITMAPHANDLERDATA
->m_insensImage
= (WXImage
*) insensImage
;
560 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
562 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
564 inline wxXPMFileHandler()
568 m_type
= wxBITMAP_TYPE_XPM
;
571 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
572 int desiredWidth
, int desiredHeight
);
573 virtual bool SaveFile(const wxBitmap
*bitmap
, const wxString
& name
,
574 wxBitmapType type
, const wxPalette
*palette
= NULL
);
577 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
579 bool wxXPMFileHandler::LoadFile( wxBitmap
*bitmap
, const wxString
& name
,
580 long WXUNUSED(flags
),
581 int WXUNUSED(desiredWidth
),
582 int WXUNUSED(desiredHeight
) )
584 Display
*dpy
= (Display
*) wxGetDisplay();
585 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
587 XpmAttributes xpmAttr
;
591 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
592 xpmAttr
.valuemask
= XpmReturnInfos
| XpmCloseness
;
593 xpmAttr
.closeness
= 40000;
594 int errorStatus
= XpmReadFileToPixmap(dpy
,
595 RootWindow(dpy
, DefaultScreen(dpy
)),
596 wxConstCast(name
.c_str(), char),
597 &pixmap
, &mask
, &xpmAttr
);
599 if (errorStatus
== XpmSuccess
)
601 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
604 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
605 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
608 unsigned int depthRet
;
610 unsigned int widthRet
, heightRet
, borderWidthRet
;
611 Window rootWindowRet
;
612 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
613 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
615 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
616 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
619 if ( xpmAttr.npixels > 2 )
621 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
624 M_BITMAPHANDLERDATA->m_depth = 1; // mono
628 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
630 // M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
632 XpmFreeAttributes(&xpmAttr
);
634 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
638 // XpmDebugError(errorStatus, name);
639 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
644 bool wxXPMFileHandler::SaveFile( const wxBitmap
*bitmap
, const wxString
& name
,
645 wxBitmapType
WXUNUSED(type
),
646 const wxPalette
*WXUNUSED(palette
))
648 if (M_BITMAPHANDLERDATA
->m_ok
&& M_BITMAPHANDLERDATA
->m_pixmap
)
650 Display
*dpy
= (Display
*) M_BITMAPHANDLERDATA
->m_display
;
651 int errorStatus
= XpmWriteFileFromPixmap(dpy
,
652 wxConstCast(name
.c_str(), char),
653 (Pixmap
) M_BITMAPHANDLERDATA
->m_pixmap
,
654 (M_BITMAPHANDLERDATA
->m_bitmapMask
? (Pixmap
) M_BITMAPHANDLERDATA
->m_bitmapMask
->GetPixmap() : (Pixmap
) 0),
655 (XpmAttributes
*) NULL
);
656 if (errorStatus
== XpmSuccess
)
665 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
667 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
669 inline wxXPMDataHandler()
673 m_type
= wxBITMAP_TYPE_XPM_DATA
;
676 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
677 int width
, int height
, int depth
= 1);
679 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
681 bool wxXPMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
682 long WXUNUSED(flags
),
683 int width
, int height
, int WXUNUSED(depth
))
685 M_BITMAPHANDLERDATA
->m_width
= width
;
686 M_BITMAPHANDLERDATA
->m_height
= height
;
687 M_BITMAPHANDLERDATA
->m_depth
= 1;
688 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
690 Display
*dpy
= (Display
*) wxGetDisplay();
691 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
693 XpmAttributes xpmAttr
;
695 xpmAttr
.valuemask
= XpmReturnInfos
; /* nothing yet, but get infos back */
697 XpmColorSymbol symbolicColors
[4];
698 if (sg_Control
&& sg_Control
->GetMainWidget())
700 symbolicColors
[0].name
= "foreground";
701 symbolicColors
[0].value
= NULL
;
702 symbolicColors
[1].name
= "background";
703 symbolicColors
[1].value
= NULL
;
704 XtVaGetValues((Widget
) sg_Control
->GetMainWidget(),
705 XmNforeground
, &symbolicColors
[0].pixel
,
706 XmNbackground
, &symbolicColors
[1].pixel
,NULL
);
707 xpmAttr
.numsymbols
= 2;
708 xpmAttr
.colorsymbols
= symbolicColors
;
709 xpmAttr
.valuemask
|= XpmColorSymbols
; // add flag
714 int ErrorStatus
= XpmCreatePixmapFromData(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)),
715 (char**) data
, &pixmap
, &mask
, &xpmAttr
);
716 if (ErrorStatus
== XpmSuccess
)
719 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
720 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
722 unsigned int depthRet
;
724 unsigned int widthRet
, heightRet
, borderWidthRet
;
725 Window rootWindowRet
;
726 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
727 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
730 if ( xpmAttr.npixels > 2 )
732 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
735 M_BITMAPHANDLERDATA->m_depth = 1; // mono
739 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
741 // M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
742 XpmFreeAttributes(&xpmAttr
);
743 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
744 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
747 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
748 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
753 // XpmDebugError(ErrorStatus, NULL);
754 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
756 return M_BITMAPHANDLERDATA
->m_ok
;
759 #endif // wxHAVE_LIB_XPM
761 void wxBitmap::InitStandardHandlers()
763 // Initialize all standard bitmap or derived class handlers here.
764 AddHandler(new wxXBMFileHandler
);
765 AddHandler(new wxXBMDataHandler
);
767 // XPM is considered standard for Motif, although it can be omitted if
768 // libXpm is not installed
770 AddHandler(new wxXPMFileHandler
);
771 AddHandler(new wxXPMDataHandler
);
772 #endif // wxHAVE_LIB_XPM
776 WXPixmap
wxBitmap::GetLabelPixmap (WXWidget w
)
779 return (WXPixmap
)NULL
;
780 // if (M_BITMAPDATA->m_image == (WXPixmap) 0)
781 return M_BITMAPDATA
->m_pixmap
;
784 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
789 if (labelPixmap) return labelPixmap;
790 things can be wrong, because colors can have been changed.
794 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
795 we got BadDrawable if the pixmap is referenced by multiples widgets
799 So, before doing thing really clean, I just do nothing; if the pixmap is
800 referenced by many widgets, Motif performs caching functions.
801 And if pixmap is referenced with multiples colors, we just have some
802 memory leaks... I hope we can deal with them...
804 // Must be destroyed, because colours can have been changed!
805 if (M_BITMAPDATA
->m_labelPixmap
)
806 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_labelPixmap
);
810 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
813 Widget widget
= (Widget
) w
;
815 while (XmIsGadget ( widget
))
816 widget
= XtParent (widget
);
817 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
819 M_BITMAPDATA
->m_labelPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
821 return M_BITMAPDATA
->m_labelPixmap
;
825 WXPixmap
wxBitmap::GetArmPixmap (WXWidget w
)
827 // if (M_BITMAPDATA->m_image == (WXPixmap) 0)
828 return M_BITMAPDATA
->m_pixmap
;
831 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
833 // See GetLabelPixmap () comment
835 // Must be destroyed, because colours can have been changed!
836 if (M_BITMAPDATA
->m_armPixmap
)
837 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_armPixmap
);
841 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
844 Widget widget
= (Widget
) w
;
846 XtVaGetValues (widget
, XmNarmColor
, &bg
, NULL
);
847 while (XmIsGadget (widget
))
848 widget
= XtParent (widget
);
849 XtVaGetValues (widget
, XmNforeground
, &fg
, NULL
);
851 M_BITMAPDATA
->m_armPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
853 return M_BITMAPDATA
->m_armPixmap
;
857 WXPixmap
wxBitmap::GetInsensPixmap (WXWidget w
)
859 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
862 return (WXPixmap
)NULL
;
863 if (M_BITMAPDATA
->m_insensPixmap
)
864 return M_BITMAPDATA
->m_insensPixmap
;
868 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XCreateInsensitivePixmap(dpy
, (Pixmap
) M_BITMAPDATA
->m_pixmap
);
869 if (M_BITMAPDATA
->m_insensPixmap
)
870 return M_BITMAPDATA
->m_insensPixmap
;
872 return M_BITMAPDATA
->m_pixmap
;
875 // if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
876 return M_BITMAPDATA
->m_pixmap
;
880 See
GetLabelPixmap () comment
881 // Must be destroyed, because colours can have been changed!
882 if (M_BITMAPDATA
->m_insensPixmap
)
883 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), (Pixmap
) M_BITMAPDATA
->m_insensPixmap
);
887 sprintf (tmp
, "Not%x", (unsigned int) M_BITMAPDATA
->m_insensImage
);
890 Widget widget
= (Widget
) w
;
892 while (XmIsGadget (widget
))
893 widget
= XtParent (widget
);
894 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
896 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
898 return M_BITMAPDATA
->m_insensPixmap
;
903 // We may need this sometime...
905 /****************************************************************************
908 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
911 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
914 This function creates a grayed-out copy of the argument pixmap, suitable
915 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
918 The return value is the new Pixmap id or zero on error. Errors include
919 a NULL display argument or an invalid Pixmap argument.
922 If one of the XLib functions fail, it will produce a X error. The
923 default X error handler prints a diagnostic and calls exit().
926 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
927 XFillRectangle(3), exit(2)
930 John R Veregge - john@puente.jpl.nasa.gov
931 Advanced Engineering and Prototyping Group (AEG)
932 Information Systems Technology Section (395)
933 Jet Propulsion Lab - Calif Institute of Technology
935 *****************************************************************************/
938 XCreateInsensitivePixmap( Display
*display
, Pixmap pixmap
)
941 static char stipple_data
[] =
943 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
944 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
945 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
946 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
949 Pixmap ipixmap
, stipple
;
950 unsigned width
, height
, depth
;
952 Window window
; /* These return values */
953 unsigned border
; /* from XGetGeometry() */
954 int x
, y
; /* are not needed. */
958 if ( NULL
== display
|| 0 == pixmap
)
961 if ( 0 == XGetGeometry( display
, pixmap
, &window
, &x
, &y
,
962 &width
, &height
, &border
, &depth
)
964 return ipixmap
; /* BadDrawable: probably an invalid pixmap */
966 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
968 stipple
= XCreateBitmapFromData( display
, pixmap
, stipple_data
, 16, 16 );
971 gc
= XCreateGC( display
, pixmap
, (XtGCMask
)0, (XGCValues
*)NULL
);
974 /* Create an identical copy of the argument pixmap.
976 ipixmap
= XCreatePixmap( display
, pixmap
, width
, height
, depth
);
979 /* Copy the argument pixmap into the new pixmap.
981 XCopyArea( display
, pixmap
, ipixmap
,
982 gc
, 0, 0, width
, height
, 0, 0 );
984 /* Refill the new pixmap using the stipple algorithm/pixmap.
986 XSetStipple( display
, gc
, stipple
);
987 XSetFillStyle( display
, gc
, FillStippled
);
988 XFillRectangle( display
, ipixmap
, gc
, 0, 0, width
, height
);
990 XFreeGC( display
, gc
);
992 XFreePixmap( display
, stipple
);
997 // Creates a bitmap with transparent areas drawn in
999 wxBitmap
wxCreateMaskedBitmap(const wxBitmap
& bitmap
, wxColour
& colour
)
1001 wxBitmap
newBitmap(bitmap
.GetWidth(),
1006 srcDC
.SelectObject(bitmap
);
1007 destDC
.SelectObject(newBitmap
);
1009 wxBrush
brush(colour
, wxSOLID
);
1010 destDC
.SetOptimization(FALSE
);
1011 destDC
.SetBackground(brush
);
1013 destDC
.Blit(0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), & srcDC
, 0, 0, wxCOPY
, TRUE
);
1021 //-----------------------------------------------------------------------------
1022 // wxImage conversion routines
1023 //-----------------------------------------------------------------------------
1027 Date: Wed, 05 Jan 2000 11:45:40 +0100
1028 From: Frits Boel <boel@niob.knaw.nl>
1029 To: julian.smart@ukonline.co.uk
1030 Subject: Patch for Motif ConvertToBitmap
1034 I've been working on a wxWin application for image processing. From the
1035 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1036 till I looked in the source code of image.cpp. I saw that converting a
1037 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1038 to the 256 colors of the palet. A very time-consuming piece of code!
1040 Because I wanted a faster application, I've made a 'patch' for this. In
1041 short: every pixel of the image is compared to a sorted list with
1042 colors. If the color is found in the list, the palette entry is
1043 returned; if the color is not found, the color palette is searched and
1044 then the palette entry is returned and the color added to the sorted
1047 Maybe there is another method for this, namely changing the palette
1048 itself (if the colors are known, as is the case with tiffs with a
1049 colormap). I did not look at this, maybe someone else did?
1051 The code of the patch is attached, have a look on it, and maybe you will
1052 ship it with the next release of wxMotif?
1057 Software engineer at Hubrecht Laboratory, The Netherlands.
1064 wxSearchColor( void );
1065 wxSearchColor( int size
, XColor
*colors
);
1066 ~wxSearchColor( void );
1068 int SearchColor( int r
, int g
, int b
);
1070 int AddColor( unsigned int value
, int pos
);
1074 unsigned int *color
;
1081 wxSearchColor::wxSearchColor( void )
1084 colors
= (XColor
*) NULL
;
1085 color
= (unsigned int *) NULL
;
1086 entry
= (int*) NULL
;
1092 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
1097 color
= new unsigned int[size
];
1098 entry
= new int [size
];
1100 for (i
= 0; i
< size
; i
++ ) {
1104 bottom
= top
= ( size
>> 1 );
1107 wxSearchColor::~wxSearchColor( void )
1109 if ( color
) delete[] color
;
1110 if ( entry
) delete[] entry
;
1113 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1115 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1120 while ( begin
<= end
) {
1122 middle
= ( begin
+ end
) >> 1;
1124 if ( value
== color
[middle
] ) {
1125 return( entry
[middle
] );
1126 } else if ( value
< color
[middle
] ) {
1134 return AddColor( value
, middle
);
1137 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1141 int max
= 3 * (65536);
1142 for ( i
= 0; i
< 256; i
++ ) {
1143 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1144 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1145 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1146 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1147 if (sum
< max
) { pixel
= i
; max
= sum
; }
1150 if ( entry
[pos
] < 0 ) {
1153 } else if ( value
< color
[pos
] ) {
1156 for ( i
= bottom
; i
< pos
; i
++ ) {
1157 color
[i
-1] = color
[i
];
1158 entry
[i
-1] = entry
[i
];
1161 color
[pos
-1] = value
;
1162 entry
[pos
-1] = pixel
;
1163 } else if ( top
< size
-1 ) {
1164 for ( i
= top
; i
>= pos
; i
-- ) {
1165 color
[i
+1] = color
[i
];
1166 entry
[i
+1] = entry
[i
];
1175 if ( top
< size
-1 ) {
1176 for ( i
= top
; i
> pos
; i
-- ) {
1177 color
[i
+1] = color
[i
];
1178 entry
[i
+1] = entry
[i
];
1181 color
[pos
+1] = value
;
1182 entry
[pos
+1] = pixel
;
1183 } else if ( bottom
> 0 ) {
1184 for ( i
= bottom
; i
< pos
; i
++ ) {
1185 color
[i
-1] = color
[i
];
1186 entry
[i
-1] = entry
[i
];
1199 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
1201 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
1202 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
1204 m_refData
= new wxBitmapRefData();
1206 int width
= image
.GetWidth();
1207 int height
= image
.GetHeight();
1209 SetHeight( height
);
1212 Display
*dpy
= (Display
*) wxGetDisplay();
1213 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1214 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1218 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1219 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1221 Create( width
, height
, bpp
);
1225 XImage
*mask_image
= (XImage
*) NULL
;
1226 if (image
.HasMask())
1228 mask_image
= XCreateImage( dpy
, vis
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1229 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
1232 // Retrieve depth info
1234 XVisualInfo vinfo_template
;
1237 vinfo_template
.visual
= vis
;
1238 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1239 vinfo_template
.depth
= bpp
;
1242 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
,
1243 &vinfo_template
, &nitem
);
1245 wxCHECK_MSG( vi
, FALSE
, wxT("no visual") );
1247 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1248 if (bpp
< 8) bpp
= 8;
1252 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1253 byte_order b_o
= RGB
;
1257 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1258 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1259 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1260 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1261 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1262 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1267 int r_mask
= image
.GetMaskRed();
1268 int g_mask
= image
.GetMaskGreen();
1269 int b_mask
= image
.GetMaskBlue();
1274 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1276 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1277 XQueryColors( dpy
, cmap
, colors
, 256 );
1280 wxSearchColor
scolor( 256, colors
);
1281 unsigned char* data
= image
.GetData();
1283 bool hasMask
= image
.HasMask();
1286 for (int y
= 0; y
< height
; y
++)
1288 for (int x
= 0; x
< width
; x
++)
1290 int r
= data
[index
];
1292 int g
= data
[index
];
1294 int b
= data
[index
];
1299 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1300 XPutPixel( mask_image
, x
, y
, 0 );
1302 XPutPixel( mask_image
, x
, y
, 1 );
1309 #if 0 // Old, slower code
1312 if (wxTheApp->m_colorCube)
1314 pixel = wxTheApp->m_colorCube
1315 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1320 int max
= 3 * (65536);
1321 for (int i
= 0; i
< 256; i
++)
1323 int rdiff
= (r
<< 8) - colors
[i
].red
;
1324 int gdiff
= (g
<< 8) - colors
[i
].green
;
1325 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1326 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1327 if (sum
< max
) { pixel
= i
; max
= sum
; }
1334 // And this is all to get the 'right' color...
1335 int pixel
= scolor
.SearchColor( r
, g
, b
);
1336 XPutPixel( data_image
, x
, y
, pixel
);
1341 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1342 XPutPixel( data_image
, x
, y
, pixel
);
1347 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1348 XPutPixel( data_image
, x
, y
, pixel
);
1357 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1358 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1359 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1360 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1361 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1362 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1364 XPutPixel( data_image
, x
, y
, pixel
);
1374 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1375 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1376 XPutImage( dpy
, (Drawable
)GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1378 XDestroyImage( data_image
);
1382 if (image
.HasMask())
1384 wxBitmap
maskBitmap(width
, height
, 1);
1386 GC gcMask
= XCreateGC( dpy
, (Pixmap
) maskBitmap
.GetPixmap(), (XtGCMask
) 0, (XGCValues
*)NULL
);
1387 XPutImage( dpy
, (Drawable
)maskBitmap
.GetPixmap(), gcMask
, mask_image
, 0, 0, 0, 0, width
, height
);
1389 XDestroyImage( mask_image
);
1390 XFreeGC( dpy
, gcMask
);
1392 wxMask
* mask
= new wxMask
;
1393 mask
->SetPixmap(maskBitmap
.GetPixmap());
1397 maskBitmap
.SetPixmapNull();
1404 wxImage
wxBitmap::ConvertToImage() const
1408 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
1410 Display
*dpy
= (Display
*) wxGetDisplay();
1411 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1412 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1414 XImage
*ximage
= XGetImage( dpy
,
1415 (Drawable
)GetPixmap(),
1417 GetWidth(), GetHeight(),
1418 AllPlanes
, ZPixmap
);
1420 wxCHECK_MSG( ximage
, wxNullImage
, wxT("couldn't create image") );
1422 image
.Create( GetWidth(), GetHeight() );
1423 char unsigned *data
= image
.GetData();
1427 XDestroyImage( ximage
);
1428 wxFAIL_MSG( wxT("couldn't create image") );
1433 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1436 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1438 GetWidth(), GetHeight() );
1440 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1444 // Retrieve depth info
1446 XVisualInfo vinfo_template
;
1449 vinfo_template
.visual
= vis
;
1450 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1451 vinfo_template
.depth
= bpp
;
1454 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1456 wxCHECK_MSG( vi
, wxNullImage
, wxT("no visual") );
1458 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1465 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1467 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1468 XQueryColors( dpy
, cmap
, colors
, 256 );
1472 for (int j
= 0; j
< GetHeight(); j
++)
1474 for (int i
= 0; i
< GetWidth(); i
++)
1476 int pixel
= XGetPixel( ximage
, i
, j
);
1479 data
[pos
] = colors
[pixel
].red
>> 8;
1480 data
[pos
+1] = colors
[pixel
].green
>> 8;
1481 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1482 } else if (bpp
== 15)
1484 data
[pos
] = (pixel
>> 7) & 0xf8;
1485 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1486 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1487 } else if (bpp
== 16)
1489 data
[pos
] = (pixel
>> 8) & 0xf8;
1490 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1491 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1494 data
[pos
] = (pixel
>> 16) & 0xff;
1495 data
[pos
+1] = (pixel
>> 8) & 0xff;
1496 data
[pos
+2] = pixel
& 0xff;
1502 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1503 if (mask_pixel == 0)
1516 XDestroyImage( ximage
);
1518 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );