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 #warning "move this to common"
28 #include "wx/xpmdecod.h"
30 #include "wx/dfb/private.h"
32 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
36 // Convert wxColour into it's quantized value in lower-precision
37 // pixel format (needed for masking by colour).
38 static wxColour
wxQuantizeColour(const wxColour
& clr
, const wxBitmap
& bmp
)
41 pixel_format_t
*pf
= bmp
.GetMGLbitmap_t()->pf
;
43 if ( pf
->redAdjust
== 0 && pf
->greenAdjust
== 0 && pf
->blueAdjust
== 0 )
46 return wxColour((unsigned char)((clr
.Red() >> pf
->redAdjust
) << pf
->redAdjust
),
47 (unsigned char)((clr
.Green() >> pf
->greenAdjust
) << pf
->greenAdjust
),
48 (unsigned char)((clr
.Blue() >> pf
->blueAdjust
) << pf
->blueAdjust
));
52 // Creates a surface that will use wxImage's pixel data (RGB only)
53 static wxIDirectFBSurfacePtr
CreateSurfaceForImage(const wxImage
& image
)
55 wxCHECK_MSG( image
.Ok(), NULL
, _T("invalid image") );
56 // FIXME_DFB: implement alpha handling by merging alpha buffer with RGB
57 // into a temporary RGBA surface
58 wxCHECK_MSG( !image
.HasAlpha(), NULL
, _T("alpha channel not supported") );
60 DFBSurfaceDescription desc
;
61 desc
.flags
= (DFBSurfaceDescriptionFlags
)
62 (DSDESC_CAPS
| DSDESC_WIDTH
| DSDESC_HEIGHT
| DSDESC_PIXELFORMAT
|
64 desc
.caps
= DSCAPS_NONE
;
65 desc
.width
= image
.GetWidth();
66 desc
.height
= image
.GetHeight();
67 desc
.pixelformat
= DSPF_RGB24
;
68 desc
.preallocated
[0].data
= image
.GetData();
69 desc
.preallocated
[0].pitch
= 3 * desc
.width
;
71 return wxIDirectFB::Get()->CreateSurface(&desc
);
74 //-----------------------------------------------------------------------------
76 //-----------------------------------------------------------------------------
78 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
80 wxMask::wxMask() : m_bitmap(NULL
)
84 wxMask::wxMask(const wxBitmap
& bitmap
)
90 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
93 Create(bitmap
, colour
);
97 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
100 Create(bitmap
, paletteIndex
);
102 #endif // wxUSE_PALETTE
104 wxMask::wxMask(const wxMask
& mask
)
106 m_bitmap
= mask
.m_bitmap
? new wxBitmap(*mask
.m_bitmap
) : NULL
;
114 #warning "move this to common code"
115 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
120 wxColour
clr(wxQuantizeColour(colour
, bitmap
));
122 wxImage
imgSrc(bitmap
.ConvertToImage());
123 imgSrc
.SetMask(false);
124 wxImage
image(imgSrc
.ConvertToMono(clr
.Red(), clr
.Green(), clr
.Blue()));
128 m_bitmap
= new wxBitmap(image
, 1);
130 return m_bitmap
->Ok();
134 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
)
137 wxPalette
*pal
= bitmap
.GetPalette();
139 wxCHECK_MSG( pal
, false, wxT("Cannot create mask from bitmap without palette") );
141 pal
->GetRGB(paletteIndex
, &r
, &g
, &b
);
143 return Create(bitmap
, wxColour(r
, g
, b
));
145 #endif // wxUSE_PALETTE
147 bool wxMask::Create(const wxBitmap
& bitmap
)
152 wxCHECK_MSG( bitmap
.Ok(), false, wxT("Invalid bitmap") );
153 wxCHECK_MSG( bitmap
.GetDepth() == 1, false, wxT("Cannot create mask from colour bitmap") );
155 m_bitmap
= new wxBitmap(bitmap
);
159 const wxBitmap
& wxMask::GetBitmap() const
161 return m_bitmap
? *m_bitmap
: wxNullBitmap
;
165 //-----------------------------------------------------------------------------
167 //-----------------------------------------------------------------------------
169 class wxBitmapRefData
: public wxObjectRefData
180 wxBitmapRefData(const wxBitmapRefData
& data
)
182 if ( data
.m_surface
)
183 m_surface
= data
.m_surface
->Clone();
185 m_mask
= data
.m_mask
? new wxMask(*data
.m_mask
) : NULL
;
187 m_palette
= data
.m_palette
? new wxPalette(*data
.m_palette
) : NULL
;
199 wxIDirectFBSurfacePtr m_surface
;
202 wxPalette
*m_palette
;
206 #define M_BITMAP ((wxBitmapRefData *)m_refData)
208 //-----------------------------------------------------------------------------
210 //-----------------------------------------------------------------------------
212 IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler
, wxObject
)
213 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxBitmapBase
)
215 wxBitmap::wxBitmap(int width
, int height
, int depth
)
217 Create(width
, height
, depth
);
220 bool wxBitmap::Create(const wxIDirectFBSurfacePtr
& surface
)
224 wxCHECK_MSG( surface
, false, _T("invalid surface") );
226 m_refData
= new wxBitmapRefData();
227 M_BITMAP
->m_surface
= surface
;
231 bool wxBitmap::Create(int width
, int height
, int depth
)
235 wxCHECK_MSG( width
> 0 && height
> 0, false, wxT("invalid bitmap size") );
236 wxCHECK_MSG( depth
== -1, false, wxT("only default depth supported now") );
238 DFBSurfaceDescription desc
;
239 desc
.flags
= (DFBSurfaceDescriptionFlags
)(
240 DSDESC_CAPS
| DSDESC_WIDTH
| DSDESC_HEIGHT
);
241 desc
.caps
= DSCAPS_NONE
;
243 desc
.height
= height
;
245 return Create(wxIDirectFB::Get()->CreateSurface(&desc
));
248 #warning "FIXME: move this to common code"
249 bool wxBitmap::CreateFromXpm(const char **bits
)
251 wxCHECK_MSG( bits
!= NULL
, false, wxT("invalid bitmap data") );
253 #if wxUSE_IMAGE && wxUSE_XPM
254 wxXPMDecoder decoder
;
255 wxImage img
= decoder
.ReadData(bits
);
256 wxCHECK_MSG( img
.Ok(), false, wxT("invalid bitmap data") );
258 *this = wxBitmap(img
);
262 wxFAIL_MSG( _T("creating bitmaps from XPMs not supported") );
264 #endif // wxUSE_IMAGE && wxUSE_XPM
268 wxBitmap::wxBitmap(const wxImage
& image
, int depth
)
270 wxCHECK_RET( image
.Ok(), wxT("invalid image") );
272 // create surface in screen's format:
273 if ( !Create(image
.GetWidth(), image
.GetHeight(), depth
) )
276 // then copy the image to it:
277 wxIDirectFBSurfacePtr
src(CreateSurfaceForImage(image
));
278 wxIDirectFBSurfacePtr dst
= M_BITMAP
->m_surface
;
280 if ( !dst
->SetBlittingFlags(DSBLIT_NOFX
) )
282 if ( !dst
->Blit(src
->GetRaw(), NULL
, 0, 0) )
285 // FIXME: implement mask creation from image's mask (or alpha channel?)
286 wxASSERT_MSG( !image
.HasMask(), _T("image masks are ignored for now") );
289 wxImage
wxBitmap::ConvertToImage() const
291 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
293 wxImage
img(GetWidth(), GetHeight());
294 wxIDirectFBSurfacePtr
dst(CreateSurfaceForImage(img
));
295 wxIDirectFBSurfacePtr src
= M_BITMAP
->m_surface
;
297 if ( !dst
->SetBlittingFlags(DSBLIT_NOFX
) )
299 if ( !dst
->Blit(src
->GetRaw(), NULL
, 0, 0) )
302 // FIXME: implement mask setting in the image
303 wxASSERT_MSG( GetMask() == NULL
, _T("bitmap masks are ignored for now") );
307 #endif // wxUSE_IMAGE
309 wxBitmap::wxBitmap(const wxString
&filename
, wxBitmapType type
)
311 LoadFile(filename
, type
);
314 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
316 wxCHECK_RET( depth
== 1, wxT("can only create mono bitmap from XBM data") );
318 wxFAIL_MSG( _T("not implemented") );
321 bool wxBitmap::Ok() const
323 return (m_refData
!= NULL
&& M_BITMAP
->m_surface
);
326 bool wxBitmap::operator==(const wxBitmap
& bmp
) const
328 // FIXME: is this the right way to compare bitmaps?
329 return (m_refData
== bmp
.m_refData
);
332 int wxBitmap::GetHeight() const
334 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
337 M_BITMAP
->m_surface
->GetSize(NULL
, &h
);
341 int wxBitmap::GetWidth() const
343 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
346 M_BITMAP
->m_surface
->GetSize(&w
, NULL
);
350 int wxBitmap::GetDepth() const
352 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
354 return M_BITMAP
->m_surface
->GetDepth();
357 wxMask
*wxBitmap::GetMask() const
359 wxCHECK_MSG( Ok(), NULL
, wxT("invalid bitmap") );
361 return M_BITMAP
->m_mask
;
364 void wxBitmap::SetMask(wxMask
*mask
)
366 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
368 delete M_BITMAP
->m_mask
;
369 M_BITMAP
->m_mask
= mask
;
372 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
374 *this = *((wxBitmap
*)(&icon
));
378 wxBitmap
wxBitmap::GetSubBitmap(const wxRect
& rect
) const
381 rect
.x
>= 0 && rect
.y
>= 0 &&
382 rect
.x
+rect
.width
<= GetWidth() &&
383 rect
.y
+rect
.height
<= GetHeight(),
385 wxT("invalid bitmap or bitmap region") );
387 // NB: DirectFB subsurfaces share the same pixels buffer, so we must
388 // clone the obtained subsurface
389 DFBRectangle r
= { rect
.x
, rect
.y
, rect
.width
, rect
.height
};
390 return wxBitmap(M_BITMAP
->m_surface
->GetSubSurface(&r
)->Clone());
393 #warning "to common code"
394 bool wxBitmap::LoadFile(const wxString
&name
, wxBitmapType type
)
398 wxBitmapHandler
*handler
= FindHandler(type
);
400 if ( handler
== NULL
)
403 if ( !image
.LoadFile(name
, type
) || !image
.Ok() )
405 wxLogError("no bitmap handler for type %d defined.", type
);
410 *this = wxBitmap(image
);
415 m_refData
= new wxBitmapRefData();
417 return handler
->LoadFile(this, name
, type
, -1, -1);
420 #warning "to common code"
421 bool wxBitmap::SaveFile(const wxString
& filename
, wxBitmapType type
, const wxPalette
*palette
) const
423 wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
425 wxBitmapHandler
*handler
= FindHandler(type
);
427 if ( handler
== NULL
)
429 wxImage image
= ConvertToImage();
432 image
.SetPalette(*palette
);
433 #endif // wxUSE_PALETTE
436 return image
.SaveFile(filename
, type
);
439 wxLogError("no bitmap handler for type %d defined.", type
);
444 return handler
->SaveFile(this, filename
, type
, palette
);
448 wxPalette
*wxBitmap::GetPalette() const
450 wxCHECK_MSG( Ok(), NULL
, wxT("invalid bitmap") );
452 return M_BITMAP
->m_palette
;
455 void wxBitmap::SetPalette(const wxPalette
& palette
)
457 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
458 wxCHECK_RET( GetDepth() > 1 && GetDepth() <= 8, wxT("cannot set palette for bitmap of this depth") );
460 delete M_BITMAP
->m_palette
;
461 M_BITMAP
->m_palette
= NULL
;
463 if ( !palette
.Ok() ) return;
465 M_BITMAP
->m_palette
= new wxPalette(palette
);
467 #endif // wxUSE_PALETTE
469 void wxBitmap::SetHeight(int height
)
473 wxFAIL_MSG( _T("SetHeight not implemented") );
476 void wxBitmap::SetWidth(int width
)
480 wxFAIL_MSG( _T("SetWidth not implemented") );
483 void wxBitmap::SetDepth(int depth
)
487 wxFAIL_MSG( _T("SetDepth not implemented") );
490 wxIDirectFBSurfacePtr
wxBitmap::GetDirectFBSurface() const
492 wxCHECK_MSG( Ok(), NULL
, wxT("invalid bitmap") );
494 return M_BITMAP
->m_surface
;
497 wxObjectRefData
*wxBitmap::CreateRefData() const
499 return new wxBitmapRefData
;
502 wxObjectRefData
*wxBitmap::CloneRefData(const wxObjectRefData
*data
) const
504 return new wxBitmapRefData(*(wxBitmapRefData
*)data
);
509 void wxBitmap::InitStandardHandlers()
511 // not wxBitmap handlers, we rely on wxImage