1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/x11/bitmap.cpp
4 // Author: Julian Smart, Robert Roebling
8 // Copyright: (c) Julian Smart, Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // for compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
15 #include "wx/bitmap.h"
20 #include "wx/dcmemory.h"
26 #include "wx/x11/private.h"
28 /* No point in using libXPM for NanoX */
31 #define wxHAVE_LIB_XPM 0
33 // Copy from the drawable to the wxImage
34 bool wxGetImageFromDrawable(GR_DRAW_ID drawable
, int srcX
, int srcY
, int width
, int height
, wxImage
& image
);
37 static WXPixmap
wxGetSubPixmap( WXDisplay
* xdisplay
, WXPixmap xpixmap
,
38 int x
, int y
, int width
, int height
,
45 #include "wx/xpmdecod.h"
46 #include "wx/wfstream.h"
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
54 IMPLEMENT_DYNAMIC_CLASS(wxMask
,wxObject
)
62 wxMask::wxMask(const wxMask
& mask
)
64 m_display
= mask
.m_display
;
73 // Duplicate the mask bitmap using the existing wxGetSubPixmap() function.
74 // There are probably/surely better ways to do it.
75 m_bitmap
= wxGetSubPixmap(m_display
, mask
.m_bitmap
,
76 0, 0, m_size
.x
, m_size
.y
,
80 wxMask::wxMask( const wxBitmap
& bitmap
, const wxColour
& colour
)
83 Create( bitmap
, colour
);
86 wxMask::wxMask( const wxBitmap
& bitmap
, int paletteIndex
)
89 Create( bitmap
, paletteIndex
);
92 wxMask::wxMask( const wxBitmap
& bitmap
)
101 XFreePixmap( (Display
*) m_display
, (Pixmap
) m_bitmap
);
104 bool wxMask::Create( const wxBitmap
& bitmap
,
105 const wxColour
& colour
)
107 m_size
= bitmap
.GetSize();
112 XFreePixmap( (Display
*) m_display
, (Pixmap
) m_bitmap
);
116 m_display
= bitmap
.GetDisplay();
118 wxImage image
= bitmap
.ConvertToImage();
119 if (!image
.IsOk()) return false;
121 m_display
= bitmap
.GetDisplay();
123 Display
*xdisplay
= (Display
*) m_display
;
124 int xscreen
= DefaultScreen( xdisplay
);
125 Window xroot
= RootWindow( xdisplay
, xscreen
);
127 m_bitmap
= (WXPixmap
) XCreatePixmap( xdisplay
, xroot
, image
.GetWidth(), image
.GetHeight(), 1 );
128 GC gc
= XCreateGC( xdisplay
, (Pixmap
) m_bitmap
, 0, NULL
);
130 XSetForeground( xdisplay
, gc
, WhitePixel(xdisplay
,xscreen
) );
131 XSetFillStyle( xdisplay
, gc
, FillSolid
);
132 XFillRectangle( xdisplay
, (Pixmap
) m_bitmap
, gc
, 0, 0, image
.GetWidth(), image
.GetHeight() );
134 unsigned char *data
= image
.GetData();
137 unsigned char red
= colour
.Red();
138 unsigned char green
= colour
.Green();
139 unsigned char blue
= colour
.Blue();
141 int bpp
= wxTheApp
->GetVisualInfo(m_display
)->m_visualDepth
;
162 XSetForeground( xdisplay
, gc
, BlackPixel(xdisplay
,xscreen
) );
164 int width
= image
.GetWidth();
165 int height
= image
.GetHeight();
166 for (int j
= 0; j
< height
; j
++)
170 for (i
= 0; i
< width
; i
++)
172 if ((data
[index
] == red
) &&
173 (data
[index
+1] == green
) &&
174 (data
[index
+2] == blue
))
183 XDrawLine( xdisplay
, (Pixmap
) m_bitmap
, gc
, start_x
, j
, i
-1, j
);
190 XDrawLine( xdisplay
, (Pixmap
) m_bitmap
, gc
, start_x
, j
, i
, j
);
193 XFreeGC( xdisplay
, gc
);
202 bool wxMask::Create( const wxBitmap
& bitmap
, int paletteIndex
)
205 wxPalette
*pal
= bitmap
.GetPalette();
207 wxCHECK_MSG( pal
, false, wxT("Cannot create mask from bitmap without palette") );
209 pal
->GetRGB(paletteIndex
, &r
, &g
, &b
);
211 return Create(bitmap
, wxColour(r
, g
, b
));
214 bool wxMask::Create( const wxBitmap
& bitmap
)
219 XFreePixmap( (Display
*) m_display
, (Pixmap
) m_bitmap
);
223 if (!bitmap
.IsOk()) return false;
225 wxCHECK_MSG( bitmap
.GetBitmap(), false, wxT("Cannot create mask from colour bitmap") );
227 m_display
= bitmap
.GetDisplay();
229 int xscreen
= DefaultScreen( (Display
*) m_display
);
230 Window xroot
= RootWindow( (Display
*) m_display
, xscreen
);
232 m_bitmap
= (WXPixmap
) XCreatePixmap( (Display
*) m_display
, xroot
, bitmap
.GetWidth(), bitmap
.GetHeight(), 1 );
234 if (!m_bitmap
) return false;
236 GC gc
= XCreateGC( (Display
*) m_display
, (Pixmap
) m_bitmap
, 0, NULL
);
238 XCopyPlane( (Display
*) m_display
, (Pixmap
) bitmap
.GetBitmap(), (Pixmap
) m_bitmap
,
239 gc
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), 0, 0, 1 );
241 XFreeGC( (Display
*) m_display
, gc
);
250 //-----------------------------------------------------------------------------
252 //-----------------------------------------------------------------------------
254 class wxBitmapRefData
: public wxGDIRefData
258 wxBitmapRefData(const wxBitmapRefData
& data
);
259 virtual ~wxBitmapRefData();
261 // shouldn't be called more than once as it doesn't free the existing data
262 bool Create(int width
, int height
, int depth
);
264 virtual bool IsOk() const { return m_pixmap
|| m_bitmap
; }
273 wxPalette
*m_palette
;
276 wxBitmapRefData::wxBitmapRefData()
288 wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData
& data
)
292 m_display
= data
.m_display
;
293 m_mask
= NULL
; // FIXME: should copy
294 m_palette
= NULL
; // FIXME: should copy
296 Create(data
.m_width
, data
.m_height
, data
.m_bpp
);
299 bool wxBitmapRefData::Create(int width
, int height
, int depth
)
305 m_display
= wxGlobalDisplay();
307 wxCHECK_MSG( m_display
, false, wxT("No display") );
309 int xscreen
= DefaultScreen(m_display
);
310 int bpp
= DefaultDepth(m_display
, xscreen
);
314 wxCHECK_MSG( (depth
== bpp
) || (depth
== 1), false,
315 wxT("invalid bitmap depth") );
318 m_pixmap
= (WXPixmap
) GrNewPixmap(width
, height
, NULL
);
319 #else // !wxUSE_NANOX
320 Window xroot
= RootWindow(m_display
, xscreen
);
322 *(depth
== 1 ? &m_bitmap
: &m_pixmap
) =
323 XCreatePixmap(m_display
, xroot
, width
, height
, depth
);
324 #endif // wxUSE_NANOX/!wxUSE_NANOX
326 wxCHECK_MSG( m_pixmap
|| m_bitmap
, false, wxT("Bitmap creation failed") );
331 wxBitmapRefData::~wxBitmapRefData()
334 XFreePixmap(m_display
, m_pixmap
);
336 XFreePixmap(m_display
, m_bitmap
);
341 //-----------------------------------------------------------------------------
345 static WXPixmap
wxGetSubPixmap( WXDisplay
* xdisplay
, WXPixmap xpixmap
,
346 int x
, int y
, int width
, int height
,
349 Display
* const dpy
= (Display
*)xdisplay
;
351 int xscreen
= DefaultScreen( dpy
);
352 Window xroot
= RootWindow( dpy
, xscreen
);
353 Visual
* xvisual
= DefaultVisual( dpy
, xscreen
);
355 XImage
* ximage
= XCreateImage( dpy
, xvisual
, depth
,
356 ZPixmap
, 0, 0, width
, height
, 32, 0 );
357 ximage
->data
= (char*)malloc( ximage
->bytes_per_line
* ximage
->height
);
358 ximage
= XGetSubImage( dpy
, (Pixmap
)xpixmap
,
360 AllPlanes
, ZPixmap
, ximage
, 0, 0 );
362 GC gc
= XCreateGC( dpy
, (Pixmap
)xpixmap
, 0, NULL
);
363 Pixmap ret
= XCreatePixmap( dpy
, xroot
,
364 width
, height
, depth
);
366 XPutImage( dpy
, ret
, gc
, ximage
,
367 0, 0, 0, 0, width
, height
);
368 XDestroyImage( ximage
);
371 return (WXPixmap
)ret
;
375 //-----------------------------------------------------------------------------
377 //-----------------------------------------------------------------------------
379 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
381 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
,wxGDIObject
)
383 bool wxBitmap::Create( int width
, int height
, int depth
)
387 wxCHECK_MSG( (width
> 0) && (height
> 0), false, wxT("invalid bitmap size") );
389 m_refData
= new wxBitmapRefData();
391 return M_BMPDATA
->Create(width
, height
, depth
);
394 bool wxBitmap::Create(const void* data
, wxBitmapType type
,
395 int width
, int height
, int depth
)
399 wxBitmapHandler
*handler
= FindHandler(type
);
401 if ( handler
== NULL
) {
402 wxLogWarning(wxT("no data bitmap handler for type %ld defined."),
408 return handler
->Create(this, data
, type
, width
, height
, depth
);
411 bool wxBitmap::Create(WXPixmap pixmap
)
414 Pixmap xpixmap
= (Pixmap
)pixmap
;
415 Display
* xdisplay
= wxGlobalDisplay();
416 int xscreen
= DefaultScreen( xdisplay
);
417 Window xroot
= RootWindow( xdisplay
, xscreen
);
419 // make a copy of the Pixmap
422 unsigned width
, height
, border
, depth
;
424 XGetGeometry( xdisplay
, (Drawable
)xpixmap
, &root
, &x
, &y
,
425 &width
, &height
, &border
, &depth
);
426 Pixmap copy
= XCreatePixmap( xdisplay
, xroot
, width
, height
, depth
);
428 GC gc
= XCreateGC( xdisplay
, copy
, 0, NULL
);
429 XCopyArea( xdisplay
, xpixmap
, copy
, gc
, 0, 0, width
, height
, 0, 0 );
430 XFreeGC( xdisplay
, gc
);
433 wxBitmapRefData
* ref
= new wxBitmapRefData();
436 ref
->m_bitmap
= copy
;
438 ref
->m_pixmap
= copy
;
440 ref
->m_display
= xdisplay
;
441 ref
->m_width
= width
;
442 ref
->m_height
= height
;
450 wxBitmap::wxBitmap(const char* const* bits
)
452 Create(bits
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
455 wxGDIRefData
*wxBitmap::CreateGDIRefData() const
457 return new wxBitmapRefData
;
460 wxGDIRefData
*wxBitmap::CloneGDIRefData(const wxGDIRefData
*data
) const
462 return new wxBitmapRefData(*static_cast<const wxBitmapRefData
*>(data
));
465 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
470 wxASSERT_MSG(image
.IsOk(), wxT("Invalid wxImage passed to wxBitmap::CreateFromImage."));
474 int w
= image
.GetWidth();
475 int h
= image
.GetHeight();
477 if (!Create(w
, h
, depth
))
480 // Unfortunately the mask has to be screen-depth since
481 // 1-bpp bitmaps don't seem to be supported
482 // TODO: implement transparent drawing, presumably
483 // by doing several blits as per the Windows
484 // implementation because Nano-X doesn't support
486 // TODO: could perhaps speed this function up
487 // by making a buffer of pixel values,
488 // and then calling GrArea to write that to the
489 // pixmap. See demos/nxroach.c.
491 bool hasMask
= image
.HasMask();
493 GC pixmapGC
= GrNewGC();
494 Pixmap pixmap
= (Pixmap
) GetPixmap();
497 Pixmap maskPixmap
= 0;
499 unsigned char maskR
= 0;
500 unsigned char maskG
= 0;
501 unsigned char maskB
= 0;
505 maskR
= image
.GetMaskRed();
506 maskG
= image
.GetMaskGreen();
507 maskB
= image
.GetMaskBlue();
510 maskPixmap
= GrNewPixmap(w
, h
, 0);
515 wxMask
* mask
= new wxMask
;
516 mask
->SetBitmap((WXPixmap
) maskPixmap
);
521 GR_COLOR lastPixmapColour
= 0;
522 GR_COLOR lastMaskColour
= 0;
525 for (i
= 0; i
< w
; i
++)
527 for (j
= 0; j
< h
; j
++)
529 unsigned char red
= image
.GetRed(i
, j
);
530 unsigned char green
= image
.GetGreen(i
, j
);
531 unsigned char blue
= image
.GetBlue(i
, j
);
533 GR_COLOR colour
= GR_RGB(red
, green
, blue
);
535 // Efficiency measure
536 if (colour
!= lastPixmapColour
|| (i
== 0 && j
== 0))
538 GrSetGCForeground(pixmapGC
, colour
);
539 lastPixmapColour
= colour
;
542 GrPoint(pixmap
, pixmapGC
, i
, j
);
546 // scan the bitmap for the transparent colour and set the corresponding
547 // pixels in the mask to BLACK and the rest to WHITE
548 if (maskR
== red
&& maskG
== green
&& maskB
== blue
)
550 colour
= GR_RGB(0, 0, 0);
554 colour
= GR_RGB(255, 255, 255);
556 if (colour
!= lastMaskColour
|| (i
== 0 && j
== 0))
558 GrSetGCForeground(maskGC
, colour
);
559 lastMaskColour
= colour
;
561 GrPoint(maskPixmap
, maskGC
, i
, j
);
566 GrDestroyGC(pixmapGC
);
576 wxCHECK_MSG( image
.IsOk(), false, wxT("invalid image") );
577 wxCHECK_MSG( depth
== -1, false, wxT("invalid bitmap depth") );
579 m_refData
= new wxBitmapRefData();
581 M_BMPDATA
->m_display
= wxGlobalDisplay();
583 Display
*xdisplay
= (Display
*) M_BMPDATA
->m_display
;
585 int xscreen
= DefaultScreen( xdisplay
);
586 Window xroot
= RootWindow( xdisplay
, xscreen
);
587 Visual
* xvisual
= DefaultVisual( xdisplay
, xscreen
);
589 int bpp
= wxTheApp
->GetVisualInfo(M_BMPDATA
->m_display
)->m_visualDepth
;
591 int width
= image
.GetWidth();
592 int height
= image
.GetHeight();
593 M_BMPDATA
->m_width
= width
;
594 M_BMPDATA
->m_height
= height
;
596 if (depth
!= 1) depth
= bpp
;
597 M_BMPDATA
->m_bpp
= depth
;
601 wxFAIL_MSG( wxT("mono images later") );
607 XImage
*data_image
= XCreateImage( xdisplay
, xvisual
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
608 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
610 if (data_image
->data
== NULL
)
612 wxLogError( wxT("Out of memory.") ); // TODO clean
616 M_BMPDATA
->m_pixmap
= XCreatePixmap( xdisplay
, xroot
, width
, height
, depth
);
618 // Create mask if necessary
619 const bool hasMask
= image
.HasMask();
621 XImage
*mask_image
= NULL
;
624 mask_image
= XCreateImage( xdisplay
, xvisual
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
625 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
627 if (mask_image
->data
== NULL
)
629 wxLogError( wxT("Out of memory.") ); // TODO clean
633 wxMask
*mask
= new wxMask();
634 mask
->SetDisplay( xdisplay
);
635 mask
->SetBitmap( (WXPixmap
) XCreatePixmap( xdisplay
, xroot
, width
, height
, 1 ) );
640 if (bpp
< 8) bpp
= 8;
644 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
645 byte_order b_o
= RGB
;
647 wxXVisualInfo
* vi
= wxTheApp
->GetVisualInfo(M_BMPDATA
->m_display
);
648 unsigned long greenMask
= vi
->m_visualGreenMask
,
649 redMask
= vi
->m_visualRedMask
,
650 blueMask
= vi
->m_visualBlueMask
;
654 if ((redMask
> greenMask
) && (greenMask
> blueMask
)) b_o
= RGB
;
655 else if ((redMask
> blueMask
) && (blueMask
> greenMask
)) b_o
= RBG
;
656 else if ((blueMask
> redMask
) && (redMask
> greenMask
)) b_o
= BRG
;
657 else if ((blueMask
> greenMask
) && (greenMask
> redMask
))b_o
= BGR
;
658 else if ((greenMask
> redMask
) && (redMask
> blueMask
)) b_o
= GRB
;
659 else if ((greenMask
> blueMask
) && (blueMask
> redMask
)) b_o
= GBR
;
662 int r_mask
= image
.GetMaskRed();
663 int g_mask
= image
.GetMaskGreen();
664 int b_mask
= image
.GetMaskBlue();
666 unsigned char* data
= image
.GetData();
667 wxASSERT_MSG( data
, wxT("No image data") );
669 unsigned char *colorCube
=
670 wxTheApp
->GetVisualInfo(M_BMPDATA
->m_display
)->m_colorCube
;
673 for (int y
= 0; y
< height
; y
++)
675 for (int x
= 0; x
< width
; x
++)
686 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
687 XPutPixel( mask_image
, x
, y
, 0 );
689 XPutPixel( mask_image
, x
, y
, 1 );
697 pixel
= colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
698 XPutPixel( data_image
, x
, y
, pixel
);
706 case RGB
: pixel
= ((r
& 0xf0) << 4) | (g
& 0xf0) | ((b
& 0xf0) >> 4); break;
707 case RBG
: pixel
= ((r
& 0xf0) << 4) | (b
& 0xf0) | ((g
& 0xf0) >> 4); break;
708 case GRB
: pixel
= ((g
& 0xf0) << 4) | (r
& 0xf0) | ((b
& 0xf0) >> 4); break;
709 case GBR
: pixel
= ((g
& 0xf0) << 4) | (b
& 0xf0) | ((r
& 0xf0) >> 4); break;
710 case BRG
: pixel
= ((b
& 0xf0) << 4) | (r
& 0xf0) | ((g
& 0xf0) >> 4); break;
711 case BGR
: pixel
= ((b
& 0xf0) << 4) | (g
& 0xf0) | ((r
& 0xf0) >> 4); break;
713 XPutPixel( data_image
, x
, y
, pixel
);
721 case RGB
: pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3); break;
722 case RBG
: pixel
= ((r
& 0xf8) << 7) | ((b
& 0xf8) << 2) | ((g
& 0xf8) >> 3); break;
723 case GRB
: pixel
= ((g
& 0xf8) << 7) | ((r
& 0xf8) << 2) | ((b
& 0xf8) >> 3); break;
724 case GBR
: pixel
= ((g
& 0xf8) << 7) | ((b
& 0xf8) << 2) | ((r
& 0xf8) >> 3); break;
725 case BRG
: pixel
= ((b
& 0xf8) << 7) | ((r
& 0xf8) << 2) | ((g
& 0xf8) >> 3); break;
726 case BGR
: pixel
= ((b
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((r
& 0xf8) >> 3); break;
728 XPutPixel( data_image
, x
, y
, pixel
);
733 // I actually don't know if for 16-bit displays, it is alway the green
734 // component or the second component which has 6 bits.
738 case RGB
: pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3); break;
739 case RBG
: pixel
= ((r
& 0xf8) << 8) | ((b
& 0xfc) << 3) | ((g
& 0xf8) >> 3); break;
740 case GRB
: pixel
= ((g
& 0xf8) << 8) | ((r
& 0xfc) << 3) | ((b
& 0xf8) >> 3); break;
741 case GBR
: pixel
= ((g
& 0xf8) << 8) | ((b
& 0xfc) << 3) | ((r
& 0xf8) >> 3); break;
742 case BRG
: pixel
= ((b
& 0xf8) << 8) | ((r
& 0xfc) << 3) | ((g
& 0xf8) >> 3); break;
743 case BGR
: pixel
= ((b
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((r
& 0xf8) >> 3); break;
745 XPutPixel( data_image
, x
, y
, pixel
);
754 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
755 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
756 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
757 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
758 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
759 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
761 XPutPixel( data_image
, x
, y
, pixel
);
770 GC gc
= XCreateGC( xdisplay
, (Pixmap
) M_BMPDATA
->m_pixmap
, 0, NULL
);
771 XPutImage( xdisplay
, (Pixmap
) M_BMPDATA
->m_pixmap
, gc
, data_image
, 0, 0, 0, 0, width
, height
);
772 XDestroyImage( data_image
);
773 XFreeGC( xdisplay
, gc
);
779 GC gc
= XCreateGC( xdisplay
, (Pixmap
) GetMask()->GetBitmap(), 0, NULL
);
780 XPutImage( xdisplay
, (Pixmap
) GetMask()->GetBitmap(), gc
, mask_image
, 0, 0, 0, 0, width
, height
);
782 XDestroyImage( mask_image
);
783 XFreeGC( xdisplay
, gc
);
792 wxImage
wxBitmap::ConvertToImage() const
796 wxCHECK_MSG( IsOk(), wxNullImage
, wxT("invalid bitmap") );
798 Display
*xdisplay
= (Display
*) M_BMPDATA
->m_display
;
799 wxASSERT_MSG( xdisplay
, wxT("No display") );
802 //int bpp = DefaultDepth(xdisplay, xscreen);
803 wxGetImageFromDrawable((Pixmap
) GetPixmap(), 0, 0, GetWidth(), GetHeight(), image
);
807 int bpp
= wxTheApp
->GetVisualInfo(M_BMPDATA
->m_display
)->m_visualDepth
;
808 XImage
*x_image
= NULL
;
811 x_image
= XGetImage( xdisplay
, (Pixmap
) GetPixmap(),
813 GetWidth(), GetHeight(),
814 AllPlanes
, ZPixmap
);
818 x_image
= XGetImage( xdisplay
, (Pixmap
) GetBitmap(),
820 GetWidth(), GetHeight(),
821 AllPlanes
, ZPixmap
);
824 wxFAIL_MSG( wxT("Ill-formed bitmap") );
827 wxCHECK_MSG( x_image
, wxNullImage
, wxT("couldn't create image") );
829 image
.Create( GetWidth(), GetHeight() );
830 char unsigned *data
= image
.GetData();
834 XDestroyImage( x_image
);
835 wxFAIL_MSG( wxT("couldn't create image") );
839 XImage
*x_image_mask
= NULL
;
842 x_image_mask
= XGetImage( xdisplay
, (Pixmap
) GetMask()->GetBitmap(),
844 GetWidth(), GetHeight(),
845 AllPlanes
, ZPixmap
);
847 image
.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
850 int red_shift_right
= 0;
851 int green_shift_right
= 0;
852 int blue_shift_right
= 0;
853 int red_shift_left
= 0;
854 int green_shift_left
= 0;
855 int blue_shift_left
= 0;
856 bool use_shift
= false;
860 wxXVisualInfo
* vi
= wxTheApp
->GetVisualInfo(M_BMPDATA
->m_display
);
862 red_shift_right
= vi
->m_visualRedShift
;
863 red_shift_left
= 8 - vi
->m_visualRedPrec
;
864 green_shift_right
= vi
->m_visualGreenShift
;
865 green_shift_left
= 8 - vi
->m_visualGreenPrec
;
866 blue_shift_right
= vi
->m_visualBlueShift
;
867 blue_shift_left
= 8 - vi
->m_visualBluePrec
;
869 use_shift
= (vi
->m_visualType
== GrayScale
) ||
870 (vi
->m_visualType
!= PseudoColor
);
878 XColor
*colors
= (XColor
*)wxTheApp
->
879 GetVisualInfo(M_BMPDATA
->m_display
)->m_visualColormap
;
881 int width
= GetWidth();
882 int height
= GetHeight();
884 for (int j
= 0; j
< height
; j
++)
886 for (int i
= 0; i
< width
; i
++)
888 unsigned long pixel
= XGetPixel( x_image
, i
, j
);
906 data
[pos
] = (unsigned char)((pixel
>> red_shift_right
) << red_shift_left
);
907 data
[pos
+1] = (unsigned char)((pixel
>> green_shift_right
) << green_shift_left
);
908 data
[pos
+2] = (unsigned char)((pixel
>> blue_shift_right
) << blue_shift_left
);
912 data
[pos
] = (unsigned char)(colors
[pixel
].red
>> 8);
913 data
[pos
+1] = (unsigned char)(colors
[pixel
].green
>> 8);
914 data
[pos
+2] = (unsigned char)(colors
[pixel
].blue
>> 8);
918 wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") );
923 int mask_pixel
= XGetPixel( x_image_mask
, i
, j
);
936 XDestroyImage( x_image
);
937 if (x_image_mask
) XDestroyImage( x_image_mask
);
943 wxBitmap::wxBitmap( const wxString
&filename
, wxBitmapType type
)
945 LoadFile( filename
, type
);
948 wxBitmap::wxBitmap( const char bits
[], int width
, int height
, int depth
)
950 m_refData
= new wxBitmapRefData
;
952 (void) Create(bits
, wxBITMAP_TYPE_XBM_DATA
, width
, height
, depth
);
955 wxBitmap::~wxBitmap()
959 int wxBitmap::GetHeight() const
961 wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") );
963 return M_BMPDATA
->m_height
;
966 int wxBitmap::GetWidth() const
968 wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") );
970 return M_BMPDATA
->m_width
;
973 int wxBitmap::GetDepth() const
975 wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") );
977 return M_BMPDATA
->m_bpp
;
980 wxMask
*wxBitmap::GetMask() const
982 wxCHECK_MSG( IsOk(), NULL
, wxT("invalid bitmap") );
984 return M_BMPDATA
->m_mask
;
987 void wxBitmap::SetMask( wxMask
*mask
)
989 wxCHECK_RET( IsOk(), wxT("invalid bitmap") );
992 if (M_BMPDATA
->m_mask
) delete M_BMPDATA
->m_mask
;
994 M_BMPDATA
->m_mask
= mask
;
997 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
1003 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
1005 wxCHECK_MSG( IsOk() &&
1006 (rect
.x
>= 0) && (rect
.y
>= 0) &&
1007 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) &&
1008 (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
1009 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
1011 wxBitmap
ret( rect
.width
, rect
.height
, M_BMPDATA
->m_bpp
);
1012 wxASSERT_MSG( ret
.IsOk(), wxT("GetSubBitmap error") );
1016 wxMask
* mask
= new wxMask();
1017 mask
->SetDisplay( GetMask()->GetDisplay() );
1018 mask
->SetBitmap( wxGetSubPixmap( GetMask()->GetDisplay(),
1019 GetMask()->GetBitmap(),
1021 rect
.width
, rect
.height
,
1024 ret
.SetMask( mask
);
1029 ret
.SetPixmap( wxGetSubPixmap( GetDisplay(),
1032 rect
.width
, rect
.height
,
1033 M_BMPDATA
->m_bpp
) );
1038 ret
.SetBitmap( wxGetSubPixmap( GetDisplay(),
1041 rect
.width
, rect
.height
,
1048 bool wxBitmap::SaveFile( const wxString
&name
, wxBitmapType type
,
1049 const wxPalette
*palette
) const
1051 wxCHECK_MSG( IsOk(), false, wxT("invalid bitmap") );
1053 wxBitmapHandler
*handler
= FindHandler(type
);
1055 // Try to save the bitmap via wxImage handlers:
1056 if (handler
== NULL
)
1058 wxImage
image(this->ConvertToImage());
1059 if (image
.IsOk()) return image
.SaveFile( name
, type
);
1064 return handler
->SaveFile(this, name
, type
, palette
);
1067 bool wxBitmap::LoadFile( const wxString
&name
, wxBitmapType type
)
1071 if (!wxFileExists(name
)) return false;
1073 wxBitmapHandler
*handler
= FindHandler(type
);
1075 if (handler
== NULL
)
1078 if (!image
.LoadFile( name
, type
))
1083 *this = wxBitmap(image
);
1089 return handler
->LoadFile(this, name
, type
, -1, -1);
1092 void wxBitmap::SetPalette(const wxPalette
& palette
)
1094 wxCHECK_RET(IsOk(), wxT("invalid bitmap"));
1095 wxCHECK_RET(GetDepth() > 1 && GetDepth() <= 8,
1096 wxT("cannot set palette for bitmap of this depth"));
1099 wxDELETE(M_BMPDATA
->m_palette
);
1101 if (!palette
.IsOk()) return;
1103 M_BMPDATA
->m_palette
= new wxPalette(palette
);
1106 wxPalette
*wxBitmap::GetPalette() const
1108 if (!IsOk()) return NULL
;
1110 return M_BMPDATA
->m_palette
;
1113 void wxBitmap::SetHeight( int height
)
1117 M_BMPDATA
->m_height
= height
;
1120 void wxBitmap::SetWidth( int width
)
1124 M_BMPDATA
->m_width
= width
;
1127 void wxBitmap::SetDepth( int depth
)
1131 M_BMPDATA
->m_bpp
= depth
;
1134 void wxBitmap::SetPixmap( WXPixmap pixmap
)
1136 if (!m_refData
) m_refData
= new wxBitmapRefData();
1138 M_BMPDATA
->m_pixmap
= (Pixmap
)pixmap
;
1141 void wxBitmap::SetBitmap( WXPixmap bitmap
)
1143 if (!m_refData
) m_refData
= new wxBitmapRefData();
1145 M_BMPDATA
->m_bitmap
= (Pixmap
)bitmap
;
1148 WXPixmap
wxBitmap::GetPixmap() const
1150 wxCHECK_MSG( IsOk(), (WXPixmap
) NULL
, wxT("invalid bitmap") );
1152 return (WXPixmap
)M_BMPDATA
->m_pixmap
;
1155 WXPixmap
wxBitmap::GetBitmap() const
1157 wxCHECK_MSG( IsOk(), (WXPixmap
) NULL
, wxT("invalid bitmap") );
1159 return (WXPixmap
)M_BMPDATA
->m_bitmap
;
1162 WXPixmap
wxBitmap::GetDrawable() const
1164 wxCHECK_MSG( IsOk(), (WXPixmap
) NULL
, wxT("invalid bitmap") );
1166 return (WXPixmap
)(M_BMPDATA
->m_bpp
== 1 ? M_BMPDATA
->m_bitmap
1167 : M_BMPDATA
->m_pixmap
);
1170 WXDisplay
*wxBitmap::GetDisplay() const
1172 wxCHECK_MSG( IsOk(), NULL
, wxT("invalid bitmap") );
1174 return M_BMPDATA
->m_display
;
1178 // Copy from the drawable to the wxImage
1179 bool wxGetImageFromDrawable(GR_DRAW_ID drawable
, int srcX
, int srcY
, int width
, int height
, wxImage
& image
)
1181 GR_SCREEN_INFO sinfo
;
1183 GR_PIXELVAL
*pixels
;
1184 GR_PALETTE
* palette
= NULL
;
1185 unsigned char rgb
[3], *pp
;
1187 GrGetScreenInfo(&sinfo
);
1189 if (sinfo
.pixtype
== MWPF_PALETTE
) {
1190 if(!(palette
= (GR_PALETTE
*) malloc(sizeof(GR_PALETTE
)))) {
1193 GrGetSystemPalette(palette
);
1196 if(!(pixels
= (GR_PIXELVAL
*) malloc(sizeof(GR_PIXELVAL
) * width
* height
)))
1201 image
.Create(width
, height
);
1203 GrReadArea(drawable
, srcX
, srcY
, width
, height
,
1207 for(x
= 0; x
< sinfo
.cols
; x
++) {
1209 pp
= (unsigned char *)pixels
+
1210 ((x
+ (y
* sinfo
.cols
)) *
1211 sizeof(GR_PIXELVAL
));
1213 switch(sinfo
.pixtype
) {
1214 /* FIXME: These may need modifying on big endian. */
1215 case MWPF_TRUECOLOR0888
:
1216 case MWPF_TRUECOLOR888
:
1222 rgb
[0] = palette
->palette
[pp
[0]].r
;
1223 rgb
[1] = palette
->palette
[pp
[0]].g
;
1224 rgb
[2] = palette
->palette
[pp
[0]].b
;
1226 case MWPF_TRUECOLOR565
:
1227 rgb
[0] = pp
[1] & 0xf8;
1228 rgb
[1] = ((pp
[1] & 0x07) << 5) |
1229 ((pp
[0] & 0xe0) >> 3);
1230 rgb
[2] = (pp
[0] & 0x1f) << 3;
1232 case MWPF_TRUECOLOR555
:
1233 rgb
[0] = (pp
[1] & 0x7c) << 1;
1234 rgb
[1] = ((pp
[1] & 0x03) << 6) |
1235 ((pp
[0] & 0xe0) >> 2);
1236 rgb
[2] = (pp
[0] & 0x1f) << 3;
1238 case MWPF_TRUECOLOR332
:
1239 rgb
[0] = pp
[0] & 0xe0;
1240 rgb
[1] = (pp
[0] & 0x1c) << 3;
1241 rgb
[2] = (pp
[0] & 0x03) << 6;
1244 fprintf(stderr
, "Unsupported pixel "
1249 image
.SetRGB(x
, y
, rgb
[0], rgb
[1], rgb
[2]);
1254 if(palette
) free(palette
);
1260 int GrGetPixelColor(GR_SCREEN_INFO
* sinfo
, GR_PALETTE
* palette
, GR_PIXELVAL pixel
,
1261 unsigned char* red
, unsigned char* green
, unsigned char* blue
)
1263 unsigned char rgb
[3], *pp
;
1265 pp
= (unsigned char*) & pixel
;
1267 switch (sinfo
.pixtype
)
1269 /* FIXME: These may need modifying on big endian. */
1270 case MWPF_TRUECOLOR0888
:
1271 case MWPF_TRUECOLOR888
:
1277 rgb
[0] = palette
->palette
[pp
[0]].r
;
1278 rgb
[1] = palette
->palette
[pp
[0]].g
;
1279 rgb
[2] = palette
->palette
[pp
[0]].b
;
1281 case MWPF_TRUECOLOR565
:
1282 rgb
[0] = pp
[1] & 0xf8;
1283 rgb
[1] = ((pp
[1] & 0x07) << 5) |
1284 ((pp
[0] & 0xe0) >> 3);
1285 rgb
[2] = (pp
[0] & 0x1f) << 3;
1287 case MWPF_TRUECOLOR555
:
1288 rgb
[0] = (pp
[1] & 0x7c) << 1;
1289 rgb
[1] = ((pp
[1] & 0x03) << 6) |
1290 ((pp
[0] & 0xe0) >> 2);
1291 rgb
[2] = (pp
[0] & 0x1f) << 3;
1293 case MWPF_TRUECOLOR332
:
1294 rgb
[0] = pp
[0] & 0xe0;
1295 rgb
[1] = (pp
[0] & 0x1c) << 3;
1296 rgb
[2] = (pp
[0] & 0x03) << 6;
1299 fprintf(stderr
, "Unsupported pixel format\n");
1314 // ============================================================================
1316 // ============================================================================
1318 #define M_BMPHANDLERDATA ((wxBitmapRefData *)bitmap->GetRefData())
1322 #if wxHAVE_LIB_XPM || wxUSE_STREAMS
1324 // ----------------------------------------------------------------------------
1326 // ----------------------------------------------------------------------------
1328 class wxXPMFileHandler
: public wxBitmapHandler
1333 SetName( wxT("XPM file") );
1334 SetExtension( wxT("xpm") );
1335 SetType( wxBITMAP_TYPE_XPM
);
1338 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
,
1340 int desiredWidth
, int desiredHeight
);
1342 virtual bool SaveFile(const wxBitmap
*bitmap
, const wxString
& name
,
1344 const wxPalette
*palette
= NULL
) const;
1346 virtual bool Create(wxBitmap
*WXUNUSED(bitmap
),
1347 const void* WXUNUSED(data
),
1348 wxBitmapType
WXUNUSED(flags
),
1349 int WXUNUSED(width
),
1350 int WXUNUSED(height
),
1351 int WXUNUSED(depth
) = 1)
1354 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
1357 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
1359 bool wxXPMFileHandler::LoadFile(wxBitmap
*bitmap
,
1360 const wxString
& name
,
1361 wxBitmapType
WXUNUSED(flags
),
1362 int WXUNUSED(desiredWidth
),
1363 int WXUNUSED(desiredHeight
))
1366 if (!bitmap
->GetRefData())
1367 bitmap
->SetRefData( new wxBitmapRefData() );
1369 M_BMPHANDLERDATA
->m_display
= wxGlobalDisplay();
1371 Display
*xdisplay
= (Display
*) M_BMPHANDLERDATA
->m_display
;
1373 int xscreen
= DefaultScreen( xdisplay
);
1374 Window xroot
= RootWindow( xdisplay
, xscreen
);
1376 int bpp
= DefaultDepth( xdisplay
, xscreen
);
1378 XpmAttributes xpmAttr
;
1379 xpmAttr
.valuemask
= XpmReturnInfos
; // nothing yet, but get infos back
1384 int ErrorStatus
= XpmReadFileToPixmap( xdisplay
, xroot
,
1385 (char*) ((const char*) name
.c_str()),
1386 &pixmap
, &mask
, &xpmAttr
);
1388 if (ErrorStatus
== XpmSuccess
)
1390 M_BMPHANDLERDATA
->m_width
= xpmAttr
.width
;
1391 M_BMPHANDLERDATA
->m_height
= xpmAttr
.height
;
1393 M_BMPHANDLERDATA
->m_bpp
= bpp
; // mono as well?
1395 XpmFreeAttributes(&xpmAttr
);
1397 M_BMPHANDLERDATA
->m_bitmap
= (Pixmap
) pixmap
;
1401 M_BMPHANDLERDATA
->m_mask
= new wxMask
;
1402 M_BMPHANDLERDATA
->m_mask
->SetBitmap( (WXPixmap
) mask
);
1403 M_BMPHANDLERDATA
->m_mask
->SetDisplay( xdisplay
);
1415 wxXPMDecoder decoder
;
1416 wxFileInputStream
stream(name
);
1419 wxImage
image(decoder
.ReadFile(stream
));
1420 return image
.IsOk() && bitmap
->CreateFromImage(image
);
1424 #else // !wxHAVE_LIB_XPM && !wxUSE_STREAMS
1426 #endif // wxHAVE_LIB_XPM / wxUSE_STREAMS
1429 bool wxXPMFileHandler::SaveFile(const wxBitmap
*bitmap
,
1430 const wxString
& name
,
1432 const wxPalette
*WXUNUSED(palette
)) const
1434 wxImage
image(bitmap
->ConvertToImage());
1436 return image
.SaveFile( name
, type
);
1441 #endif // wxHAVE_LIB_XPM || wxUSE_STREAMS
1443 // ----------------------------------------------------------------------------
1445 // ----------------------------------------------------------------------------
1447 class wxXPMDataHandler
: public wxBitmapHandler
1449 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
1453 SetName( wxT("XPM data") );
1454 SetExtension( wxT("xpm") );
1455 SetType( wxBITMAP_TYPE_XPM_DATA
);
1458 virtual bool LoadFile(wxBitmap
*WXUNUSED(bitmap
),
1459 const wxString
& WXUNUSED(name
),
1460 wxBitmapType
WXUNUSED(flags
),
1461 int WXUNUSED(desiredWidth
),
1462 int WXUNUSED(desiredHeight
))
1465 virtual bool SaveFile(const wxBitmap
*WXUNUSED(bitmap
),
1466 const wxString
& WXUNUSED(name
),
1467 wxBitmapType
WXUNUSED(type
),
1468 const wxPalette
*WXUNUSED(palette
) = NULL
) const
1471 virtual bool Create(wxBitmap
*bitmap
, const void* data
, wxBitmapType flags
,
1472 int width
, int height
, int depth
= 1);
1475 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
1477 bool wxXPMDataHandler::Create(wxBitmap
*bitmap
, const void* bits
,
1478 wxBitmapType
WXUNUSED(flags
),
1479 int WXUNUSED(width
), int WXUNUSED(height
), int WXUNUSED(depth
))
1482 wxCHECK_MSG( bits
!= NULL
, false, wxT("invalid bitmap data") );
1484 if (!bitmap
->GetRefData())
1485 bitmap
->SetRefData( new wxBitmapRefData() );
1487 M_BMPHANDLERDATA
->m_display
= wxGlobalDisplay();
1489 Display
*xdisplay
= (Display
*) M_BMPHANDLERDATA
->m_display
;
1491 int xscreen
= DefaultScreen( xdisplay
);
1492 Window xroot
= RootWindow( xdisplay
, xscreen
);
1494 int bpp
= DefaultDepth( xdisplay
, xscreen
);
1496 XpmAttributes xpmAttr
;
1497 xpmAttr
.valuemask
= XpmReturnInfos
; // nothing yet, but get infos back
1502 int ErrorStatus
= XpmCreatePixmapFromData( xdisplay
, xroot
, (char**) bits
,
1503 &pixmap
, &mask
, &xpmAttr
);
1505 if (ErrorStatus
== XpmSuccess
)
1507 M_BMPHANDLERDATA
->m_width
= xpmAttr
.width
;
1508 M_BMPHANDLERDATA
->m_height
= xpmAttr
.height
;
1510 M_BMPHANDLERDATA
->m_bpp
= bpp
; // mono as well?
1513 unsigned int depthRet
;
1515 unsigned int widthRet
, heightRet
, borderWidthRet
;
1516 XGetGeometry( xdisplay
, pixmap
, &xroot
, &xRet
, &yRet
,
1517 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
1519 wxASSERT_MSG( bpp
== (int)depthRet
, wxT("colour depth mismatch") );
1520 #endif // wxDEBUG_LEVEL
1522 XpmFreeAttributes(&xpmAttr
);
1524 M_BMPHANDLERDATA
->m_pixmap
= (Pixmap
) pixmap
;
1528 M_BMPHANDLERDATA
->m_mask
= new wxMask
;
1529 M_BMPHANDLERDATA
->m_mask
->SetBitmap( (WXPixmap
) mask
);
1530 M_BMPHANDLERDATA
->m_mask
->SetDisplay( xdisplay
);
1540 #else // !wxHAVE_LIB_XPM
1541 wxXPMDecoder decoder
;
1542 wxImage
image(decoder
.ReadData((const char **)bits
));
1543 return image
.IsOk() && bitmap
->CreateFromImage(image
);
1544 #endif // wxHAVE_LIB_XPM/!wxHAVE_LIB_XPM
1549 // ----------------------------------------------------------------------------
1551 // ----------------------------------------------------------------------------
1553 class WXDLLEXPORT wxXBMDataHandler
: public wxBitmapHandler
1555 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler
)
1557 inline wxXBMDataHandler()
1559 SetName( wxT("XBM data") );
1560 SetExtension( wxT("xbm") );
1561 SetType( wxBITMAP_TYPE_XBM_DATA
);
1564 virtual bool LoadFile(wxBitmap
*WXUNUSED(bitmap
),
1565 const wxString
& WXUNUSED(name
),
1566 wxBitmapType
WXUNUSED(flags
),
1567 int WXUNUSED(desiredWidth
),
1568 int WXUNUSED(desiredHeight
))
1571 virtual bool SaveFile(const wxBitmap
*WXUNUSED(bitmap
),
1572 const wxString
& WXUNUSED(name
),
1573 wxBitmapType
WXUNUSED(type
),
1574 const wxPalette
*WXUNUSED(palette
) = NULL
) const
1577 virtual bool Create(wxBitmap
*bitmap
, const void* data
, wxBitmapType type
,
1578 int width
, int height
, int depth
= 1);
1581 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler
, wxBitmapHandler
)
1583 bool wxXBMDataHandler::Create( wxBitmap
*bitmap
, const void* bits
,
1584 wxBitmapType
WXUNUSED(type
),
1585 int width
, int height
, int WXUNUSED(depth
))
1588 if (!bitmap
->GetRefData())
1589 bitmap
->SetRefData( new wxBitmapRefData() );
1591 M_BMPHANDLERDATA
->m_display
= wxGlobalDisplay();
1593 Display
*xdisplay
= (Display
*) M_BMPHANDLERDATA
->m_display
;
1595 int xscreen
= DefaultScreen( xdisplay
);
1596 Window xroot
= RootWindow( xdisplay
, xscreen
);
1598 M_BMPHANDLERDATA
->m_mask
= NULL
;
1599 M_BMPHANDLERDATA
->m_bitmap
=
1600 XCreateBitmapFromData(xdisplay
, xroot
,
1601 (char *) bits
, width
, height
);
1602 M_BMPHANDLERDATA
->m_width
= width
;
1603 M_BMPHANDLERDATA
->m_height
= height
;
1604 M_BMPHANDLERDATA
->m_bpp
= 1;
1608 wxCHECK_MSG( M_BMPHANDLERDATA
->m_bitmap
, false,
1609 wxT("couldn't create bitmap") );
1613 void wxBitmap::InitStandardHandlers()
1615 AddHandler(new wxXBMDataHandler
);
1617 #if wxHAVE_LIB_XPM || wxUSE_STREAMS
1618 AddHandler(new wxXPMFileHandler
);
1620 AddHandler(new wxXPMDataHandler
);