1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart, Robert Roebling
8 // Copyright: (c) Julian Smart, Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "bitmap.h"
16 #include "wx/bitmap.h"
22 #include "wx/dcmemory.h"
25 #include "wx/x11/private.h"
27 /* No point in using libXPM for NanoX */
30 #define wxHAVE_LIB_XPM 0
32 // Copy from the drawable to the wxImage
33 bool wxGetImageFromDrawable(GR_DRAW_ID drawable
, int srcX
, int srcY
, int width
, int height
, wxImage
& image
);
40 #include "wx/xpmdecod.h"
41 #include "wx/wfstream.h"
46 //-----------------------------------------------------------------------------
48 //-----------------------------------------------------------------------------
50 IMPLEMENT_DYNAMIC_CLASS(wxMask
,wxObject
)
58 wxMask::wxMask( const wxBitmap
& bitmap
, const wxColour
& colour
)
61 Create( bitmap
, colour
);
64 wxMask::wxMask( const wxBitmap
& bitmap
, int paletteIndex
)
67 Create( bitmap
, paletteIndex
);
70 wxMask::wxMask( const wxBitmap
& bitmap
)
79 XFreePixmap( (Display
*) m_display
, (Pixmap
) m_bitmap
);
82 bool wxMask::Create( const wxBitmap
& bitmap
,
83 const wxColour
& colour
)
88 XFreePixmap( (Display
*) m_display
, (Pixmap
) m_bitmap
);
92 m_display
= bitmap
.GetDisplay();
94 wxImage
image( bitmap
);
95 if (!image
.Ok()) return FALSE
;
97 m_display
= bitmap
.GetDisplay();
99 Display
*xdisplay
= (Display
*) m_display
;
101 int xscreen
= DefaultScreen( xdisplay
);
102 Window xroot
= RootWindow( xdisplay
, xscreen
);
103 Visual
* xvisual
= DefaultVisual( xdisplay
, xscreen
);
104 int bpp
= DefaultDepth( xdisplay
, xscreen
);
106 m_bitmap
= (WXPixmap
) XCreatePixmap( xdisplay
, xroot
, image
.GetWidth(), image
.GetHeight(), 1 );
107 GC gc
= XCreateGC( xdisplay
, (Pixmap
) m_bitmap
, 0, NULL
);
109 XSetForeground( xdisplay
, gc
, WhitePixel(xdisplay
,xscreen
) );
110 XSetFillStyle( xdisplay
, gc
, FillSolid
);
111 XFillRectangle( xdisplay
, (Pixmap
) m_bitmap
, gc
, 0, 0, image
.GetWidth(), image
.GetHeight() );
113 unsigned char *data
= image
.GetData();
116 unsigned char red
= colour
.Red();
117 unsigned char green
= colour
.Green();
118 unsigned char blue
= colour
.Blue();
120 XVisualInfo vinfo_template
;
123 vinfo_template
.visual
= xvisual
;
124 vinfo_template
.visualid
= XVisualIDFromVisual( xvisual
);
125 vinfo_template
.depth
= bpp
;
128 vi
= XGetVisualInfo( xdisplay
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
129 wxASSERT_MSG( vi
, wxT("No visual info") );
131 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
135 green
= green
& 0xf8;
141 green
= green
& 0xfc;
147 green
= green
& 0xf0;
151 XSetForeground( xdisplay
, gc
, BlackPixel(xdisplay
,xscreen
) );
153 int width
= image
.GetWidth();
154 int height
= image
.GetHeight();
155 for (int j
= 0; j
< height
; j
++)
159 for (i
= 0; i
< width
; i
++)
161 if ((data
[index
] == red
) &&
162 (data
[index
+1] == green
) &&
163 (data
[index
+2] == blue
))
172 XDrawLine( xdisplay
, (Pixmap
) m_bitmap
, gc
, start_x
, j
, i
-1, j
);
179 XDrawLine( xdisplay
, (Pixmap
) m_bitmap
, gc
, start_x
, j
, i
, j
);
182 XFreeGC( xdisplay
, gc
);
191 bool wxMask::Create( const wxBitmap
& bitmap
, int paletteIndex
)
194 wxPalette
*pal
= bitmap
.GetPalette();
196 wxCHECK_MSG( pal
, FALSE
, wxT("Cannot create mask from bitmap without palette") );
198 pal
->GetRGB(paletteIndex
, &r
, &g
, &b
);
200 return Create(bitmap
, wxColour(r
, g
, b
));
203 bool wxMask::Create( const wxBitmap
& bitmap
)
208 XFreePixmap( (Display
*) m_display
, (Pixmap
) m_bitmap
);
212 if (!bitmap
.Ok()) return FALSE
;
214 wxCHECK_MSG( bitmap
.GetBitmap(), FALSE
, wxT("Cannot create mask from colour bitmap") );
216 m_display
= bitmap
.GetDisplay();
218 int xscreen
= DefaultScreen( (Display
*) m_display
);
219 Window xroot
= RootWindow( (Display
*) m_display
, xscreen
);
221 m_bitmap
= (WXPixmap
) XCreatePixmap( (Display
*) m_display
, xroot
, bitmap
.GetWidth(), bitmap
.GetHeight(), 1 );
223 if (!m_bitmap
) return FALSE
;
225 GC gc
= XCreateGC( (Display
*) m_display
, (Pixmap
) m_bitmap
, 0, NULL
);
227 XCopyPlane( (Display
*) m_display
, (Pixmap
) bitmap
.GetBitmap(), (Pixmap
) m_bitmap
,
228 gc
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), 0, 0, 1 );
230 XFreeGC( (Display
*) m_display
, gc
);
239 //-----------------------------------------------------------------------------
241 //-----------------------------------------------------------------------------
243 class wxBitmapRefData
: public wxObjectRefData
251 WXDisplay
*m_display
;
256 wxPalette
*m_palette
;
259 wxBitmapRefData::wxBitmapRefData()
264 m_mask
= (wxMask
*) NULL
;
268 m_palette
= (wxPalette
*) NULL
;
271 wxBitmapRefData::~wxBitmapRefData()
273 if (m_pixmap
) XFreePixmap( (Display
*) m_display
, (Pixmap
) m_pixmap
);
274 if (m_bitmap
) XFreePixmap( (Display
*) m_display
, (Pixmap
) m_bitmap
);
275 if (m_mask
) delete m_mask
;
276 if (m_palette
) delete m_palette
;
279 //-----------------------------------------------------------------------------
281 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
283 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
,wxGDIObject
)
289 wxBitmap::wxBitmap( int width
, int height
, int depth
)
291 Create( width
, height
, depth
);
294 bool wxBitmap::Create( int width
, int height
, int depth
)
298 wxCHECK_MSG( (width
> 0) && (height
> 0), FALSE
, wxT("invalid bitmap size") )
300 m_refData
= new wxBitmapRefData();
302 M_BMPDATA
->m_display
= wxGlobalDisplay();
304 wxASSERT_MSG( M_BMPDATA
->m_display
, wxT("No display") );
306 int xscreen
= DefaultScreen( (Display
*) M_BMPDATA
->m_display
);
307 Window xroot
= RootWindow( (Display
*) M_BMPDATA
->m_display
, xscreen
);
309 int bpp
= DefaultDepth( (Display
*) M_BMPDATA
->m_display
, xscreen
);
310 if (depth
== -1) depth
= bpp
;
312 wxCHECK_MSG( (depth
== bpp
) ||
313 (depth
== 1), FALSE
, wxT("invalid bitmap depth") )
315 M_BMPDATA
->m_mask
= (wxMask
*) NULL
;
316 M_BMPDATA
->m_width
= width
;
317 M_BMPDATA
->m_height
= height
;
320 M_BMPDATA
->m_pixmap
= (WXPixmap
) GrNewPixmap(width
, height
, NULL
);
321 M_BMPDATA
->m_bpp
= bpp
;
323 wxASSERT_MSG( M_BMPDATA
->m_pixmap
, wxT("Bitmap creation failed") );
327 M_BMPDATA
->m_bitmap
= (WXPixmap
) XCreatePixmap( (Display
*) M_BMPDATA
->m_display
, xroot
, width
, height
, 1 );
329 wxASSERT_MSG( M_BMPDATA
->m_bitmap
, wxT("Bitmap creation failed") );
331 M_BMPDATA
->m_bpp
= 1;
335 M_BMPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap( (Display
*) M_BMPDATA
->m_display
, xroot
, width
, height
, depth
);
337 wxASSERT_MSG( M_BMPDATA
->m_pixmap
, wxT("Pixmap creation failed") );
339 M_BMPDATA
->m_bpp
= depth
;
345 bool wxBitmap::CreateFromXpm( const char **bits
)
351 wxCHECK_MSG( bits
!= NULL
, FALSE
, wxT("invalid bitmap data") )
353 m_refData
= new wxBitmapRefData();
355 M_BMPDATA
->m_display
= wxGlobalDisplay();
357 Display
*xdisplay
= (Display
*) M_BMPDATA
->m_display
;
359 int xscreen
= DefaultScreen( xdisplay
);
360 Window xroot
= RootWindow( xdisplay
, xscreen
);
362 int bpp
= DefaultDepth( xdisplay
, xscreen
);
364 XpmAttributes xpmAttr
;
365 xpmAttr
.valuemask
= XpmReturnInfos
; // nothing yet, but get infos back
370 int ErrorStatus
= XpmCreatePixmapFromData( xdisplay
, xroot
, (char**) bits
, &pixmap
, &mask
, &xpmAttr
);
372 if (ErrorStatus
== XpmSuccess
)
374 M_BMPDATA
->m_width
= xpmAttr
.width
;
375 M_BMPDATA
->m_height
= xpmAttr
.height
;
377 M_BMPDATA
->m_bpp
= bpp
; // mono as well?
380 unsigned int depthRet
;
382 unsigned int widthRet
, heightRet
, borderWidthRet
;
383 XGetGeometry( xdisplay
, pixmap
, &xroot
, &xRet
, &yRet
,
384 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
386 wxASSERT_MSG( bpp
== (int)depthRet
, wxT("colour depth mismatch") )
389 XpmFreeAttributes(&xpmAttr
);
391 M_BMPDATA
->m_pixmap
= (WXPixmap
) pixmap
;
395 M_BMPDATA
->m_mask
= new wxMask
;
396 M_BMPDATA
->m_mask
->SetBitmap( (WXPixmap
) mask
);
397 M_BMPDATA
->m_mask
->SetDisplay( xdisplay
);
408 wxXPMDecoder decoder
;
409 wxImage
image(decoder
.ReadData(bits
));
411 return CreateFromImage(image
);
419 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
424 wxASSERT_MSG(image
.Ok(), "Invalid wxImage passed to wxBitmap::CreateFromImage.");
428 int w
= image
.GetWidth();
429 int h
= image
.GetHeight();
431 if (!Create(w
, h
, depth
))
434 // Unfortunately the mask has to be screen-depth since
435 // 1-bpp bitmaps don't seem to be supported
436 // TODO: implement transparent drawing, presumably
437 // by doing several blits as per the Windows
438 // implementation because Nano-X doesn't support
440 // TODO: could perhaps speed this function up
441 // by making a buffer of pixel values,
442 // and then calling GrArea to write that to the
443 // pixmap. See demos/nxroach.c.
445 bool hasMask
= image
.HasMask();
447 GC pixmapGC
= GrNewGC();
448 Pixmap pixmap
= (Pixmap
) GetPixmap();
451 Pixmap maskPixmap
= 0;
453 unsigned char maskR
= 0;
454 unsigned char maskG
= 0;
455 unsigned char maskB
= 0;
459 maskR
= image
.GetMaskRed();
460 maskG
= image
.GetMaskGreen();
461 maskB
= image
.GetMaskBlue();
464 maskPixmap
= GrNewPixmap(w
, h
, 0);
469 wxMask
* mask
= new wxMask
;
470 mask
->SetBitmap((WXPixmap
) maskPixmap
);
475 GR_COLOR lastPixmapColour
= 0;
476 GR_COLOR lastMaskColour
= 0;
479 for (i
= 0; i
< w
; i
++)
481 for (j
= 0; j
< h
; j
++)
483 unsigned char red
= image
.GetRed(i
, j
);
484 unsigned char green
= image
.GetGreen(i
, j
);
485 unsigned char blue
= image
.GetBlue(i
, j
);
487 GR_COLOR colour
= GR_RGB(red
, green
, blue
);
489 // Efficiency measure
490 if (colour
!= lastPixmapColour
|| (i
== 0 && j
== 0))
492 GrSetGCForeground(pixmapGC
, colour
);
493 lastPixmapColour
= colour
;
496 GrPoint(pixmap
, pixmapGC
, i
, j
);
500 // scan the bitmap for the transparent colour and set the corresponding
501 // pixels in the mask to BLACK and the rest to WHITE
502 if (maskR
== red
&& maskG
== green
&& maskB
== blue
)
504 colour
= GR_RGB(0, 0, 0);
508 colour
= GR_RGB(255, 255, 255);
510 if (colour
!= lastMaskColour
|| (i
== 0 && j
== 0))
512 GrSetGCForeground(maskGC
, colour
);
513 lastMaskColour
= colour
;
515 GrPoint(maskPixmap
, maskGC
, i
, j
);
520 GrDestroyGC(pixmapGC
);
530 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
531 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
533 m_refData
= new wxBitmapRefData();
535 M_BMPDATA
->m_display
= wxGlobalDisplay();
537 Display
*xdisplay
= (Display
*) M_BMPDATA
->m_display
;
539 int xscreen
= DefaultScreen( xdisplay
);
540 Window xroot
= RootWindow( xdisplay
, xscreen
);
541 Visual
* xvisual
= DefaultVisual( xdisplay
, xscreen
);
543 int bpp
= DefaultDepth( xdisplay
, xscreen
);
545 int width
= image
.GetWidth();
546 int height
= image
.GetHeight();
547 M_BMPDATA
->m_width
= width
;
548 M_BMPDATA
->m_height
= height
;
550 if (depth
!= 1) depth
= bpp
;
551 M_BMPDATA
->m_bpp
= depth
;
555 wxFAIL_MSG( "mono images later" );
561 XImage
*data_image
= XCreateImage( xdisplay
, xvisual
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
562 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
564 if (data_image
->data
== NULL
)
566 wxLogError( wxT("Out of memory.") ); // TODO clean
570 M_BMPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap( xdisplay
, xroot
, width
, height
, depth
);
574 XImage
*mask_image
= (XImage
*) NULL
;
577 mask_image
= XCreateImage( xdisplay
, xvisual
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
578 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
580 if (mask_image
->data
== NULL
)
582 wxLogError( wxT("Out of memory.") ); // TODO clean
586 wxMask
*mask
= new wxMask();
587 mask
->SetDisplay( xdisplay
);
588 mask
->SetBitmap( (WXPixmap
) XCreatePixmap( xdisplay
, xroot
, width
, height
, 1 ) );
595 XVisualInfo vinfo_template
;
598 vinfo_template
.visual
= xvisual
;
599 vinfo_template
.visualid
= XVisualIDFromVisual( xvisual
);
600 vinfo_template
.depth
= bpp
;
603 vi
= XGetVisualInfo( xdisplay
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
604 wxASSERT_MSG( vi
, wxT("No visual info") );
606 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
607 if (bpp
< 8) bpp
= 8;
611 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
612 byte_order b_o
= RGB
;
616 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
617 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RBG
;
618 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
619 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
620 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
621 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
626 int r_mask
= image
.GetMaskRed();
627 int g_mask
= image
.GetMaskGreen();
628 int b_mask
= image
.GetMaskBlue();
630 unsigned char* data
= image
.GetData();
631 wxASSERT_MSG( data
, "No image data" );
633 bool hasMask
= image
.HasMask();
636 for (int y
= 0; y
< height
; y
++)
638 for (int x
= 0; x
< width
; x
++)
649 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
650 XPutPixel( mask_image
, x
, y
, 0 );
652 XPutPixel( mask_image
, x
, y
, 1 );
661 if (wxTheApp
->m_colorCube
)
663 pixel
= wxTheApp
->m_colorCube
[ ((r
& 0xf8) << 7) + ((g
& 0xf8) << 2) + ((b
& 0xf8) >> 3) ];
667 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
668 GdkColor
*colors
= cmap
->colors
;
669 int max
= 3 * (65536);
671 for (int i
= 0; i
< cmap
->size
; i
++)
673 int rdiff
= (r
<< 8) - colors
[i
].red
;
674 int gdiff
= (g
<< 8) - colors
[i
].green
;
675 int bdiff
= (b
<< 8) - colors
[i
].blue
;
676 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
677 if (sum
< max
) { pixel
= i
; max
= sum
; }
681 XPutPixel( data_image
, x
, y
, pixel
);
689 case RGB
: pixel
= ((r
& 0xf0) << 4) | (g
& 0xf0) | ((b
& 0xf0) >> 4); break;
690 case RBG
: pixel
= ((r
& 0xf0) << 4) | (b
& 0xf0) | ((g
& 0xf0) >> 4); break;
691 case GRB
: pixel
= ((g
& 0xf0) << 4) | (r
& 0xf0) | ((b
& 0xf0) >> 4); break;
692 case GBR
: pixel
= ((g
& 0xf0) << 4) | (b
& 0xf0) | ((r
& 0xf0) >> 4); break;
693 case BRG
: pixel
= ((b
& 0xf0) << 4) | (r
& 0xf0) | ((g
& 0xf0) >> 4); break;
694 case BGR
: pixel
= ((b
& 0xf0) << 4) | (g
& 0xf0) | ((r
& 0xf0) >> 4); break;
696 XPutPixel( data_image
, x
, y
, pixel
);
704 case RGB
: pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3); break;
705 case RBG
: pixel
= ((r
& 0xf8) << 7) | ((b
& 0xf8) << 2) | ((g
& 0xf8) >> 3); break;
706 case GRB
: pixel
= ((g
& 0xf8) << 7) | ((r
& 0xf8) << 2) | ((b
& 0xf8) >> 3); break;
707 case GBR
: pixel
= ((g
& 0xf8) << 7) | ((b
& 0xf8) << 2) | ((r
& 0xf8) >> 3); break;
708 case BRG
: pixel
= ((b
& 0xf8) << 7) | ((r
& 0xf8) << 2) | ((g
& 0xf8) >> 3); break;
709 case BGR
: pixel
= ((b
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((r
& 0xf8) >> 3); break;
711 XPutPixel( data_image
, x
, y
, pixel
);
716 // I actually don't know if for 16-bit displays, it is alway the green
717 // component or the second component which has 6 bits.
721 case RGB
: pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3); break;
722 case RBG
: pixel
= ((r
& 0xf8) << 8) | ((b
& 0xfc) << 3) | ((g
& 0xf8) >> 3); break;
723 case GRB
: pixel
= ((g
& 0xf8) << 8) | ((r
& 0xfc) << 3) | ((b
& 0xf8) >> 3); break;
724 case GBR
: pixel
= ((g
& 0xf8) << 8) | ((b
& 0xfc) << 3) | ((r
& 0xf8) >> 3); break;
725 case BRG
: pixel
= ((b
& 0xf8) << 8) | ((r
& 0xfc) << 3) | ((g
& 0xf8) >> 3); break;
726 case BGR
: pixel
= ((b
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((r
& 0xf8) >> 3); break;
728 XPutPixel( data_image
, x
, y
, pixel
);
737 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
738 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
739 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
740 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
741 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
742 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
744 XPutPixel( data_image
, x
, y
, pixel
);
753 GC gc
= XCreateGC( xdisplay
, (Pixmap
) M_BMPDATA
->m_pixmap
, 0, NULL
);
754 XPutImage( xdisplay
, (Pixmap
) M_BMPDATA
->m_pixmap
, gc
, data_image
, 0, 0, 0, 0, width
, height
);
756 XSync(wxGlobalDisplay(), False
);
759 XDestroyImage( data_image
);
760 XFreeGC( xdisplay
, gc
);
766 GC gc
= XCreateGC( xdisplay
, (Pixmap
) GetMask()->GetBitmap(), 0, NULL
);
767 XPutImage( xdisplay
, (Pixmap
) GetMask()->GetBitmap(), gc
, mask_image
, 0, 0, 0, 0, width
, height
);
769 XDestroyImage( mask_image
);
770 XFreeGC( xdisplay
, gc
);
779 static void wxCalcPrecAndShift( unsigned long mask
, int *shift
, int *prec
)
784 while (!(mask
& 0x1))
797 wxImage
wxBitmap::ConvertToImage() const
801 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
803 Display
*xdisplay
= (Display
*) M_BMPDATA
->m_display
;
804 wxASSERT_MSG( xdisplay
, wxT("No display") );
806 int xscreen
= DefaultScreen( xdisplay
);
807 Visual
* xvisual
= DefaultVisual( xdisplay
, xscreen
);
809 int bpp
= DefaultDepth( xdisplay
, xscreen
);
812 wxGetImageFromDrawable((Pixmap
) GetPixmap(), 0, 0, GetWidth(), GetHeight(), image
);
816 XImage
*x_image
= NULL
;
819 x_image
= XGetImage( xdisplay
, (Pixmap
) GetPixmap(),
821 GetWidth(), GetHeight(),
822 AllPlanes
, ZPixmap
);
826 x_image
= XGetImage( xdisplay
, (Pixmap
) GetBitmap(),
828 GetWidth(), GetHeight(),
829 AllPlanes
, ZPixmap
);
832 wxFAIL_MSG( wxT("Ill-formed bitmap") );
835 wxCHECK_MSG( x_image
, wxNullImage
, wxT("couldn't create image") );
837 image
.Create( GetWidth(), GetHeight() );
838 char unsigned *data
= image
.GetData();
842 XDestroyImage( x_image
);
843 wxFAIL_MSG( wxT("couldn't create image") );
847 XImage
*x_image_mask
= NULL
;
850 x_image_mask
= XGetImage( xdisplay
, (Pixmap
) GetMask()->GetBitmap(),
852 GetWidth(), GetHeight(),
853 AllPlanes
, ZPixmap
);
855 image
.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
858 int red_shift_right
= 0;
859 int green_shift_right
= 0;
860 int blue_shift_right
= 0;
861 int red_shift_left
= 0;
862 int green_shift_left
= 0;
863 int blue_shift_left
= 0;
864 bool use_shift
= FALSE
;
870 XVisualInfo vinfo_template
;
873 vinfo_template
.visual
= xvisual
;
874 vinfo_template
.visualid
= XVisualIDFromVisual( xvisual
);
875 vinfo_template
.depth
= bpp
;
878 vi
= XGetVisualInfo( xdisplay
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
879 wxASSERT_MSG( vi
, wxT("No visual info") );
881 int red_prec
,green_prec
,blue_prec
;
882 int red_shift
,green_shift
,blue_shift
;
883 wxCalcPrecAndShift( vi
->red_mask
, &red_shift
, &red_prec
);
884 wxCalcPrecAndShift( vi
->green_mask
, &green_shift
, &green_prec
);
885 wxCalcPrecAndShift( vi
->blue_mask
, &blue_shift
, &blue_prec
);
886 if (bpp
== 16) bpp
= red_prec
+ green_prec
+ blue_prec
;
888 red_shift_right
= red_shift
;
889 red_shift_left
= 8-red_prec
;
890 green_shift_right
= green_shift
;
891 green_shift_left
= 8-green_prec
;
892 blue_shift_right
= blue_shift
;
893 blue_shift_left
= 8-blue_prec
;
896 use_shift
= (vi
->visual
->c_class
== TrueColor
) || (vi
->visual
->c_class
== DirectColor
);
909 // GdkColormap *cmap = gtk_widget_get_default_colormap();
911 int width
= GetWidth();
912 int height
= GetHeight();
914 for (int j
= 0; j
< height
; j
++)
916 for (int i
= 0; i
< width
; i
++)
918 unsigned long pixel
= XGetPixel( x_image
, i
, j
);
936 data
[pos
] = (pixel
>> red_shift_right
) << red_shift_left
;
937 data
[pos
+1] = (pixel
>> green_shift_right
) << green_shift_left
;
938 data
[pos
+2] = (pixel
>> blue_shift_right
) << blue_shift_left
;
941 else if (cmap
->colors
)
943 data
[pos
] = cmap
->colors
[pixel
].red
>> 8;
944 data
[pos
+1] = cmap
->colors
[pixel
].green
>> 8;
945 data
[pos
+2] = cmap
->colors
[pixel
].blue
>> 8;
950 wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") );
955 int mask_pixel
= XGetPixel( x_image_mask
, i
, j
);
968 XDestroyImage( x_image
);
969 if (x_image_mask
) XDestroyImage( x_image_mask
);
975 wxBitmap::wxBitmap( const wxBitmap
& bmp
)
980 wxBitmap::wxBitmap( const wxString
&filename
, int type
)
982 LoadFile( filename
, type
);
985 wxBitmap::wxBitmap( const char bits
[], int width
, int height
, int WXUNUSED(depth
) )
988 m_refData
= new wxBitmapRefData();
990 M_BMPDATA
->m_display
= wxGlobalDisplay();
992 Display
*xdisplay
= (Display
*) M_BMPDATA
->m_display
;
994 int xscreen
= DefaultScreen( xdisplay
);
995 Window xroot
= RootWindow( xdisplay
, xscreen
);
997 M_BMPDATA
->m_mask
= (wxMask
*) NULL
;
998 M_BMPDATA
->m_bitmap
= (WXPixmap
) XCreateBitmapFromData( xdisplay
, xroot
, (char *) bits
, width
, height
);
999 M_BMPDATA
->m_width
= width
;
1000 M_BMPDATA
->m_height
= height
;
1001 M_BMPDATA
->m_bpp
= 1;
1003 wxCHECK_RET( M_BMPDATA
->m_bitmap
, wxT("couldn't create bitmap") );
1006 wxBitmap::~wxBitmap()
1010 wxBitmap
& wxBitmap::operator = ( const wxBitmap
& bmp
)
1012 if ( m_refData
!= bmp
.m_refData
)
1018 bool wxBitmap::operator == ( const wxBitmap
& bmp
) const
1020 return m_refData
== bmp
.m_refData
;
1023 bool wxBitmap::operator != ( const wxBitmap
& bmp
) const
1025 return m_refData
!= bmp
.m_refData
;
1028 bool wxBitmap::Ok() const
1030 return (m_refData
!= NULL
);
1033 int wxBitmap::GetHeight() const
1035 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1037 return M_BMPDATA
->m_height
;
1040 int wxBitmap::GetWidth() const
1042 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1044 return M_BMPDATA
->m_width
;
1047 int wxBitmap::GetDepth() const
1049 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
1051 return M_BMPDATA
->m_bpp
;
1054 wxMask
*wxBitmap::GetMask() const
1056 wxCHECK_MSG( Ok(), (wxMask
*) NULL
, wxT("invalid bitmap") );
1058 return M_BMPDATA
->m_mask
;
1061 void wxBitmap::SetMask( wxMask
*mask
)
1063 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
1065 if (M_BMPDATA
->m_mask
) delete M_BMPDATA
->m_mask
;
1067 M_BMPDATA
->m_mask
= mask
;
1070 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
1076 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
1078 wxCHECK_MSG( Ok() &&
1079 (rect
.x
>= 0) && (rect
.y
>= 0) &&
1080 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) && (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
1081 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
1083 wxBitmap
ret( rect
.width
, rect
.height
, M_BMPDATA
->m_bpp
);
1084 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
1087 wxFAIL_MSG( "wxBitmap::GetSubBitmap not yet implemented" );
1090 if (ret
.GetPixmap())
1092 GdkGC
*gc
= gdk_gc_new( ret
.GetPixmap() );
1093 gdk_draw_pixmap( ret
.GetPixmap(), gc
, GetPixmap(), rect
.x
, rect
.y
, 0, 0, rect
.width
, rect
.height
);
1094 gdk_gc_destroy( gc
);
1098 GdkGC
*gc
= gdk_gc_new( ret
.GetBitmap() );
1099 gdk_wx_draw_bitmap( ret
.GetBitmap(), gc
, GetBitmap(), rect
.x
, rect
.y
, 0, 0, rect
.width
, rect
.height
);
1100 gdk_gc_destroy( gc
);
1105 wxMask
*mask
= new wxMask
;
1106 mask
->m_bitmap
= gdk_pixmap_new( wxGetRootWindow()->window
, rect
.width
, rect
.height
, 1 );
1108 GdkGC
*gc
= gdk_gc_new( mask
->m_bitmap
);
1109 gdk_wx_draw_bitmap( mask
->m_bitmap
, gc
, M_BMPDATA
->m_mask
->m_bitmap
, 0, 0, rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1110 gdk_gc_destroy( gc
);
1112 ret
.SetMask( mask
);
1119 bool wxBitmap::SaveFile( const wxString
&name
, int type
, wxPalette
*WXUNUSED(palette
) )
1121 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid bitmap") );
1123 // Try to save the bitmap via wxImage handlers:
1125 wxImage
image( *this );
1126 if (image
.Ok()) return image
.SaveFile( name
, type
);
1132 bool wxBitmap::LoadFile( const wxString
&name
, int type
)
1136 if (!wxFileExists(name
)) return FALSE
;
1139 if (type
== wxBITMAP_TYPE_XPM
)
1143 m_refData
= new wxBitmapRefData();
1145 M_BMPDATA
->m_display
= wxGlobalDisplay();
1147 Display
*xdisplay
= (Display
*) M_BMPDATA
->m_display
;
1149 int xscreen
= DefaultScreen( xdisplay
);
1150 Window xroot
= RootWindow( xdisplay
, xscreen
);
1152 int bpp
= DefaultDepth( xdisplay
, xscreen
);
1154 XpmAttributes xpmAttr
;
1155 xpmAttr
.valuemask
= XpmReturnInfos
; // nothing yet, but get infos back
1160 int ErrorStatus
= XpmReadFileToPixmap( xdisplay
, xroot
, (char*) name
.c_str(), &pixmap
, &mask
, &xpmAttr
);
1162 if (ErrorStatus
== XpmSuccess
)
1164 M_BMPDATA
->m_width
= xpmAttr
.width
;
1165 M_BMPDATA
->m_height
= xpmAttr
.height
;
1167 M_BMPDATA
->m_bpp
= bpp
; // mono as well?
1169 XpmFreeAttributes(&xpmAttr
);
1171 M_BMPDATA
->m_bitmap
= (WXPixmap
) pixmap
;
1175 M_BMPDATA
->m_mask
= new wxMask
;
1176 M_BMPDATA
->m_mask
->SetBitmap( (WXPixmap
) mask
);
1177 M_BMPDATA
->m_mask
->SetDisplay( xdisplay
);
1188 wxXPMDecoder decoder
;
1189 wxFileInputStream
stream(name
);
1192 wxImage
image(decoder
.ReadFile(stream
));
1194 return CreateFromImage(image
);
1210 else // try if wxImage can load it
1213 if (!image
.LoadFile( name
, type
)) return FALSE
;
1214 if (image
.Ok()) *this = image
.ConvertToBitmap();
1221 wxPalette
*wxBitmap::GetPalette() const
1223 if (!Ok()) return (wxPalette
*) NULL
;
1225 return M_BMPDATA
->m_palette
;
1228 void wxBitmap::SetHeight( int height
)
1230 if (!m_refData
) m_refData
= new wxBitmapRefData();
1232 M_BMPDATA
->m_height
= height
;
1235 void wxBitmap::SetWidth( int width
)
1237 if (!m_refData
) m_refData
= new wxBitmapRefData();
1239 M_BMPDATA
->m_width
= width
;
1242 void wxBitmap::SetDepth( int depth
)
1244 if (!m_refData
) m_refData
= new wxBitmapRefData();
1246 M_BMPDATA
->m_bpp
= depth
;
1249 void wxBitmap::SetPixmap( WXPixmap pixmap
)
1251 if (!m_refData
) m_refData
= new wxBitmapRefData();
1253 M_BMPDATA
->m_pixmap
= pixmap
;
1256 void wxBitmap::SetBitmap( WXPixmap bitmap
)
1258 if (!m_refData
) m_refData
= new wxBitmapRefData();
1260 M_BMPDATA
->m_bitmap
= bitmap
;
1263 WXPixmap
wxBitmap::GetPixmap() const
1265 wxCHECK_MSG( Ok(), (WXPixmap
) NULL
, wxT("invalid bitmap") );
1267 return M_BMPDATA
->m_pixmap
;
1270 WXPixmap
wxBitmap::GetBitmap() const
1272 wxCHECK_MSG( Ok(), (WXPixmap
) NULL
, wxT("invalid bitmap") );
1274 return M_BMPDATA
->m_bitmap
;
1277 WXDisplay
*wxBitmap::GetDisplay() const
1279 wxCHECK_MSG( Ok(), (WXDisplay
*) NULL
, wxT("invalid bitmap") );
1281 return M_BMPDATA
->m_display
;
1285 // Copy from the drawable to the wxImage
1286 bool wxGetImageFromDrawable(GR_DRAW_ID drawable
, int srcX
, int srcY
, int width
, int height
, wxImage
& image
)
1288 GR_SCREEN_INFO sinfo
;
1290 GR_PIXELVAL
*pixels
;
1291 GR_PALETTE
* palette
= NULL
;
1292 unsigned char rgb
[3], *pp
;
1294 GrGetScreenInfo(&sinfo
);
1296 if (sinfo
.pixtype
== MWPF_PALETTE
) {
1297 if(!(palette
= (GR_PALETTE
*) malloc(sizeof(GR_PALETTE
)))) {
1300 GrGetSystemPalette(palette
);
1303 if(!(pixels
= (GR_PIXELVAL
*) malloc(sizeof(GR_PIXELVAL
) * width
* height
)))
1308 image
.Create(width
, height
);
1310 GrReadArea(drawable
, srcX
, srcY
, width
, height
,
1314 for(x
= 0; x
< sinfo
.cols
; x
++) {
1316 pp
= (unsigned char *)pixels
+
1317 ((x
+ (y
* sinfo
.cols
)) *
1318 sizeof(GR_PIXELVAL
));
1320 switch(sinfo
.pixtype
) {
1321 /* FIXME: These may need modifying on big endian. */
1322 case MWPF_TRUECOLOR0888
:
1323 case MWPF_TRUECOLOR888
:
1329 rgb
[0] = palette
->palette
[pp
[0]].r
;
1330 rgb
[1] = palette
->palette
[pp
[0]].g
;
1331 rgb
[2] = palette
->palette
[pp
[0]].b
;
1333 case MWPF_TRUECOLOR565
:
1334 rgb
[0] = pp
[1] & 0xf8;
1335 rgb
[1] = ((pp
[1] & 0x07) << 5) |
1336 ((pp
[0] & 0xe0) >> 3);
1337 rgb
[2] = (pp
[0] & 0x1f) << 3;
1339 case MWPF_TRUECOLOR555
:
1340 rgb
[0] = (pp
[1] & 0x7c) << 1;
1341 rgb
[1] = ((pp
[1] & 0x03) << 6) |
1342 ((pp
[0] & 0xe0) >> 2);
1343 rgb
[2] = (pp
[0] & 0x1f) << 3;
1345 case MWPF_TRUECOLOR332
:
1346 rgb
[0] = pp
[0] & 0xe0;
1347 rgb
[1] = (pp
[0] & 0x1c) << 3;
1348 rgb
[2] = (pp
[0] & 0x03) << 6;
1351 fprintf(stderr
, "Unsupported pixel "
1356 image
.SetRGB(x
, y
, rgb
[0], rgb
[1], rgb
[2]);
1361 if(palette
) free(palette
);
1367 int GrGetPixelColor(GR_SCREEN_INFO
* sinfo
, GR_PALETTE
* palette
, GR_PIXELVAL pixel
,
1368 unsigned char* red
, unsigned char* green
, unsigned char* blue
)
1370 unsigned char rgb
[3], *pp
;
1372 pp
= (unsigned char*) & pixel
;
1374 switch (sinfo
.pixtype
)
1376 /* FIXME: These may need modifying on big endian. */
1377 case MWPF_TRUECOLOR0888
:
1378 case MWPF_TRUECOLOR888
:
1384 rgb
[0] = palette
->palette
[pp
[0]].r
;
1385 rgb
[1] = palette
->palette
[pp
[0]].g
;
1386 rgb
[2] = palette
->palette
[pp
[0]].b
;
1388 case MWPF_TRUECOLOR565
:
1389 rgb
[0] = pp
[1] & 0xf8;
1390 rgb
[1] = ((pp
[1] & 0x07) << 5) |
1391 ((pp
[0] & 0xe0) >> 3);
1392 rgb
[2] = (pp
[0] & 0x1f) << 3;
1394 case MWPF_TRUECOLOR555
:
1395 rgb
[0] = (pp
[1] & 0x7c) << 1;
1396 rgb
[1] = ((pp
[1] & 0x03) << 6) |
1397 ((pp
[0] & 0xe0) >> 2);
1398 rgb
[2] = (pp
[0] & 0x1f) << 3;
1400 case MWPF_TRUECOLOR332
:
1401 rgb
[0] = pp
[0] & 0xe0;
1402 rgb
[1] = (pp
[0] & 0x1c) << 3;
1403 rgb
[2] = (pp
[0] & 0x03) << 6;
1406 fprintf(stderr
, "Unsupported pixel format\n");