1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/dfb/bitmap.cpp
3 // Purpose: wxBitmap implementation
4 // Author: Vaclav Slavik
7 // Copyright: (c) 2006 REA Elektronik GmbH
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
23 #include "wx/bitmap.h"
24 #include "wx/colour.h"
27 #include "wx/dfb/private.h"
29 //-----------------------------------------------------------------------------
31 //-----------------------------------------------------------------------------
33 // pitch = stride = # of bytes between the start of N-th line and (N+1)-th line
34 static void CopyPixelsAndSwapRGB(unsigned w
, unsigned h
,
35 const unsigned char *src
,
40 unsigned src_advance
= src_pitch
- 3 * w
;
41 unsigned dst_advance
= dst_pitch
- 3 * w
;
42 for ( unsigned y
= 0; y
< h
; y
++, src
+= src_advance
, dst
+= dst_advance
)
44 for ( unsigned x
= 0; x
< w
; x
++, src
+= 3, dst
+= 3 )
46 // copy with RGB -> BGR translation:
54 static void CopySurfaceToImage(const wxIDirectFBSurfacePtr
& surface
,
57 wxCHECK_RET( surface
->GetPixelFormat() == DSPF_RGB24
,
58 _T("unexpected pixel format") );
60 wxIDirectFBSurface::Locked
locked(surface
, DSLF_READ
);
61 wxCHECK_RET( locked
.ptr
, _T("failed to lock surface") );
63 CopyPixelsAndSwapRGB(image
.GetWidth(), image
.GetHeight(),
64 (unsigned char*)locked
.ptr
, locked
.pitch
,
65 image
.GetData(), image
.GetWidth() * 3);
68 static void CopyImageToSurface(const wxImage
& image
,
69 const wxIDirectFBSurfacePtr
& surface
)
71 wxCHECK_RET( surface
->GetPixelFormat() == DSPF_RGB24
,
72 _T("unexpected pixel format") );
74 wxIDirectFBSurface::Locked
locked(surface
, DSLF_WRITE
);
75 wxCHECK_RET( locked
.ptr
, _T("failed to lock surface") );
77 CopyPixelsAndSwapRGB(image
.GetWidth(), image
.GetHeight(),
78 image
.GetData(), image
.GetWidth() * 3,
79 (unsigned char*)locked
.ptr
, locked
.pitch
);
82 // Creates a surface that will use wxImage's pixel data (RGB only)
83 static wxIDirectFBSurfacePtr
CreateSurfaceForImage(const wxImage
& image
)
85 wxCHECK_MSG( image
.Ok(), NULL
, _T("invalid image") );
86 // FIXME_DFB: implement alpha handling by merging alpha buffer with RGB
87 // into a temporary RGBA surface
88 wxCHECK_MSG( !image
.HasAlpha(), NULL
, _T("alpha channel not supported") );
90 // NB: wxImage uses RGB order of bytes while DirectFB uses BGR, so we
91 // cannot use preallocated surface that shares data with wxImage, we
92 // have to copy the data to temporary surface instead
93 DFBSurfaceDescription desc
;
94 desc
.flags
= (DFBSurfaceDescriptionFlags
)
95 (DSDESC_CAPS
| DSDESC_WIDTH
| DSDESC_HEIGHT
| DSDESC_PIXELFORMAT
);
96 desc
.caps
= DSCAPS_NONE
;
97 desc
.width
= image
.GetWidth();
98 desc
.height
= image
.GetHeight();
99 desc
.pixelformat
= DSPF_RGB24
;
101 return wxIDirectFB::Get()->CreateSurface(&desc
);
104 //-----------------------------------------------------------------------------
106 //-----------------------------------------------------------------------------
108 class wxBitmapRefData
: public wxObjectRefData
119 wxBitmapRefData(const wxBitmapRefData
& data
)
121 m_surface
= data
.m_surface
? data
.m_surface
->Clone() : NULL
;
123 m_mask
= data
.m_mask
? new wxMask(*data
.m_mask
) : NULL
;
125 m_palette
= data
.m_palette
? new wxPalette(*data
.m_palette
) : NULL
;
129 virtual ~wxBitmapRefData()
137 wxIDirectFBSurfacePtr m_surface
;
140 wxPalette
*m_palette
;
144 #define M_BITMAP ((wxBitmapRefData *)m_refData)
146 //-----------------------------------------------------------------------------
148 //-----------------------------------------------------------------------------
150 IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler
, wxBitmapHandlerBase
)
151 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxBitmapBase
)
153 wxBitmap::wxBitmap(int width
, int height
, int depth
)
155 Create(width
, height
, depth
);
158 bool wxBitmap::Create(const wxIDirectFBSurfacePtr
& surface
)
162 wxCHECK_MSG( surface
, false, _T("invalid surface") );
164 m_refData
= new wxBitmapRefData();
165 M_BITMAP
->m_surface
= surface
;
169 bool wxBitmap::Create(int width
, int height
, int depth
)
173 wxCHECK_MSG( width
> 0 && height
> 0, false, wxT("invalid bitmap size") );
174 wxCHECK_MSG( depth
== -1, false, wxT("only default depth supported now") );
176 DFBSurfaceDescription desc
;
177 desc
.flags
= (DFBSurfaceDescriptionFlags
)(
178 DSDESC_CAPS
| DSDESC_WIDTH
| DSDESC_HEIGHT
);
179 desc
.caps
= DSCAPS_NONE
;
181 desc
.height
= height
;
183 return Create(wxIDirectFB::Get()->CreateSurface(&desc
));
187 wxBitmap::wxBitmap(const wxImage
& image
, int depth
)
189 wxCHECK_RET( image
.Ok(), wxT("invalid image") );
191 // create surface in screen's format:
192 if ( !Create(image
.GetWidth(), image
.GetHeight(), depth
) )
195 // then copy the image to it:
196 wxIDirectFBSurfacePtr dst
= M_BITMAP
->m_surface
;
198 if ( dst
->GetPixelFormat() == DSPF_RGB24
)
200 CopyImageToSurface(image
, dst
);
204 // wxBitmap uses different pixel format, so we have to use a temporary
205 // surface and blit to the bitmap via it:
206 wxIDirectFBSurfacePtr
src(CreateSurfaceForImage(image
));
207 CopyImageToSurface(image
, src
);
209 if ( !dst
->SetBlittingFlags(DSBLIT_NOFX
) )
211 if ( !dst
->Blit(src
->GetRaw(), NULL
, 0, 0) )
215 // FIXME: implement mask creation from image's mask (or alpha channel?)
216 wxASSERT_MSG( !image
.HasMask(), _T("image masks are ignored for now") );
219 wxImage
wxBitmap::ConvertToImage() const
221 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
223 wxImage
img(GetWidth(), GetHeight());
224 wxIDirectFBSurfacePtr src
= M_BITMAP
->m_surface
;
226 if ( src
->GetPixelFormat() == DSPF_RGB24
)
228 CopySurfaceToImage(src
, img
);
232 // wxBitmap uses different pixel format, so we have to use a temporary
233 // surface and blit to the bitmap via it:
234 wxIDirectFBSurfacePtr
dst(CreateSurfaceForImage(img
));
236 if ( !dst
->SetBlittingFlags(DSBLIT_NOFX
) )
238 if ( !dst
->Blit(src
->GetRaw(), NULL
, 0, 0) )
241 CopySurfaceToImage(dst
, img
);
244 // FIXME: implement mask setting in the image
245 wxASSERT_MSG( GetMask() == NULL
, _T("bitmap masks are ignored for now") );
249 #endif // wxUSE_IMAGE
251 wxBitmap::wxBitmap(const wxString
&filename
, wxBitmapType type
)
253 LoadFile(filename
, type
);
256 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
258 wxCHECK_RET( depth
== 1, wxT("can only create mono bitmap from XBM data") );
260 wxFAIL_MSG( _T("not implemented") );
263 bool wxBitmap::IsOk() const
265 return (m_refData
!= NULL
&& M_BITMAP
->m_surface
);
268 int wxBitmap::GetHeight() const
270 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
273 M_BITMAP
->m_surface
->GetSize(NULL
, &h
);
277 int wxBitmap::GetWidth() const
279 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
282 M_BITMAP
->m_surface
->GetSize(&w
, NULL
);
286 int wxBitmap::GetDepth() const
288 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
290 return M_BITMAP
->m_surface
->GetDepth();
293 wxMask
*wxBitmap::GetMask() const
295 wxCHECK_MSG( Ok(), NULL
, wxT("invalid bitmap") );
297 return M_BITMAP
->m_mask
;
300 void wxBitmap::SetMask(wxMask
*mask
)
302 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
305 delete M_BITMAP
->m_mask
;
306 M_BITMAP
->m_mask
= mask
;
309 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
311 *this = *((wxBitmap
*)(&icon
));
315 wxBitmap
wxBitmap::GetSubBitmap(const wxRect
& rect
) const
318 rect
.x
>= 0 && rect
.y
>= 0 &&
319 rect
.x
+rect
.width
<= GetWidth() &&
320 rect
.y
+rect
.height
<= GetHeight(),
322 wxT("invalid bitmap or bitmap region") );
324 // NB: DirectFB subsurfaces share the same pixels buffer, so we must
325 // clone the obtained subsurface
326 DFBRectangle r
= { rect
.x
, rect
.y
, rect
.width
, rect
.height
};
327 return wxBitmap(M_BITMAP
->m_surface
->GetSubSurface(&r
)->Clone());
330 #warning "to common code"
331 bool wxBitmap::LoadFile(const wxString
&name
, wxBitmapType type
)
335 wxBitmapHandler
*handler
= FindHandler(type
);
337 if ( handler
== NULL
)
340 if ( !image
.LoadFile(name
, type
) || !image
.Ok() )
342 wxLogError(_("No bitmap handler for type %d defined."), type
);
347 *this = wxBitmap(image
);
352 m_refData
= new wxBitmapRefData();
354 return handler
->LoadFile(this, name
, type
, -1, -1);
357 #warning "to common code"
358 bool wxBitmap::SaveFile(const wxString
& filename
, wxBitmapType type
, const wxPalette
*palette
) const
360 wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
362 wxBitmapHandler
*handler
= FindHandler(type
);
364 if ( handler
== NULL
)
366 wxImage image
= ConvertToImage();
369 image
.SetPalette(*palette
);
370 #endif // wxUSE_PALETTE
373 return image
.SaveFile(filename
, type
);
376 wxLogError(_("No bitmap handler for type %d defined."), type
);
381 return handler
->SaveFile(this, filename
, type
, palette
);
385 wxPalette
*wxBitmap::GetPalette() const
387 wxCHECK_MSG( Ok(), NULL
, wxT("invalid bitmap") );
389 return M_BITMAP
->m_palette
;
392 void wxBitmap::SetPalette(const wxPalette
& palette
)
394 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
395 wxCHECK_RET( GetDepth() > 1 && GetDepth() <= 8, wxT("cannot set palette for bitmap of this depth") );
398 delete M_BITMAP
->m_palette
;
399 M_BITMAP
->m_palette
= NULL
;
401 if ( !palette
.Ok() ) return;
403 M_BITMAP
->m_palette
= new wxPalette(palette
);
405 #endif // wxUSE_PALETTE
407 void wxBitmap::SetHeight(int height
)
411 wxFAIL_MSG( _T("SetHeight not implemented") );
414 void wxBitmap::SetWidth(int width
)
418 wxFAIL_MSG( _T("SetWidth not implemented") );
421 void wxBitmap::SetDepth(int depth
)
425 wxFAIL_MSG( _T("SetDepth not implemented") );
428 wxIDirectFBSurfacePtr
wxBitmap::GetDirectFBSurface() const
430 wxCHECK_MSG( Ok(), NULL
, wxT("invalid bitmap") );
432 return M_BITMAP
->m_surface
;
435 wxObjectRefData
*wxBitmap::CreateRefData() const
437 return new wxBitmapRefData
;
440 wxObjectRefData
*wxBitmap::CloneRefData(const wxObjectRefData
*data
) const
442 return new wxBitmapRefData(*(wxBitmapRefData
*)data
);
447 void wxBitmap::InitStandardHandlers()
449 // not wxBitmap handlers, we rely on wxImage