Files
wxWidgets/src/dfb/bitmap.cpp
Vadim Zeitlin 55ccdb93e4 COW cleanup patch (1583966):
1. perform deep comparison for the classes for which it makes sense in the
   ports where this wasn't done yet
2. remove (shallow) comparison operators for the classes for which it does
   not make sense (such as wxBitmap)
3. makes wxBitmap use COW on all ports
4. adds wxObject::IsRefTo()
5. centralizes and improves COW docs


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42752 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2006-10-30 19:26:48 +00:00

380 lines
9.4 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/dfb/bitmap.cpp
// Purpose: wxBitmap implementation
// Author: Vaclav Slavik
// Created: 2006-08-04
// RCS-ID: $Id$
// Copyright: (c) 2006 REA Elektronik GmbH
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/log.h"
#endif
#include "wx/bitmap.h"
#include "wx/colour.h"
#include "wx/image.h"
#include "wx/dfb/private.h"
//-----------------------------------------------------------------------------
// helpers
//-----------------------------------------------------------------------------
// Creates a surface that will use wxImage's pixel data (RGB only)
static wxIDirectFBSurfacePtr CreateSurfaceForImage(const wxImage& image)
{
wxCHECK_MSG( image.Ok(), NULL, _T("invalid image") );
// FIXME_DFB: implement alpha handling by merging alpha buffer with RGB
// into a temporary RGBA surface
wxCHECK_MSG( !image.HasAlpha(), NULL, _T("alpha channel not supported") );
DFBSurfaceDescription desc;
desc.flags = (DFBSurfaceDescriptionFlags)
(DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT |
DSDESC_PREALLOCATED);
desc.caps = DSCAPS_NONE;
desc.width = image.GetWidth();
desc.height = image.GetHeight();
desc.pixelformat = DSPF_RGB24;
desc.preallocated[0].data = image.GetData();
desc.preallocated[0].pitch = 3 * desc.width;
return wxIDirectFB::Get()->CreateSurface(&desc);
}
//-----------------------------------------------------------------------------
// wxBitmapRefData
//-----------------------------------------------------------------------------
class wxBitmapRefData: public wxObjectRefData
{
public:
wxBitmapRefData()
{
m_mask = NULL;
#if wxUSE_PALETTE
m_palette = NULL;
#endif
}
wxBitmapRefData(const wxBitmapRefData& data)
{
if ( data.m_surface )
m_surface = data.m_surface->Clone();
m_mask = data.m_mask ? new wxMask(*data.m_mask) : NULL;
#if wxUSE_PALETTE
m_palette = data.m_palette ? new wxPalette(*data.m_palette) : NULL;
#endif
}
~wxBitmapRefData()
{
delete m_mask;
#if wxUSE_PALETTE
delete m_palette;
#endif
}
wxIDirectFBSurfacePtr m_surface;
wxMask *m_mask;
#if wxUSE_PALETTE
wxPalette *m_palette;
#endif
};
#define M_BITMAP ((wxBitmapRefData *)m_refData)
//-----------------------------------------------------------------------------
// wxBitmap
//-----------------------------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler, wxBitmapHandlerBase)
IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxBitmapBase)
wxBitmap::wxBitmap(int width, int height, int depth)
{
Create(width, height, depth);
}
bool wxBitmap::Create(const wxIDirectFBSurfacePtr& surface)
{
UnRef();
wxCHECK_MSG( surface, false, _T("invalid surface") );
m_refData = new wxBitmapRefData();
M_BITMAP->m_surface = surface;
return true;
}
bool wxBitmap::Create(int width, int height, int depth)
{
UnRef();
wxCHECK_MSG( width > 0 && height > 0, false, wxT("invalid bitmap size") );
wxCHECK_MSG( depth == -1, false, wxT("only default depth supported now") );
DFBSurfaceDescription desc;
desc.flags = (DFBSurfaceDescriptionFlags)(
DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT);
desc.caps = DSCAPS_NONE;
desc.width = width;
desc.height = height;
return Create(wxIDirectFB::Get()->CreateSurface(&desc));
}
#if wxUSE_IMAGE
wxBitmap::wxBitmap(const wxImage& image, int depth)
{
wxCHECK_RET( image.Ok(), wxT("invalid image") );
// create surface in screen's format:
if ( !Create(image.GetWidth(), image.GetHeight(), depth) )
return;
// then copy the image to it:
wxIDirectFBSurfacePtr src(CreateSurfaceForImage(image));
wxIDirectFBSurfacePtr dst = M_BITMAP->m_surface;
if ( !dst->SetBlittingFlags(DSBLIT_NOFX) )
return;
if ( !dst->Blit(src->GetRaw(), NULL, 0, 0) )
return;
// FIXME: implement mask creation from image's mask (or alpha channel?)
wxASSERT_MSG( !image.HasMask(), _T("image masks are ignored for now") );
}
wxImage wxBitmap::ConvertToImage() const
{
wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
wxImage img(GetWidth(), GetHeight());
wxIDirectFBSurfacePtr dst(CreateSurfaceForImage(img));
wxIDirectFBSurfacePtr src = M_BITMAP->m_surface;
if ( !dst->SetBlittingFlags(DSBLIT_NOFX) )
return wxNullImage;
if ( !dst->Blit(src->GetRaw(), NULL, 0, 0) )
return wxNullImage;
// FIXME: implement mask setting in the image
wxASSERT_MSG( GetMask() == NULL, _T("bitmap masks are ignored for now") );
return img;
}
#endif // wxUSE_IMAGE
wxBitmap::wxBitmap(const wxString &filename, wxBitmapType type)
{
LoadFile(filename, type);
}
wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
{
wxCHECK_RET( depth == 1, wxT("can only create mono bitmap from XBM data") );
wxFAIL_MSG( _T("not implemented") );
}
bool wxBitmap::IsOk() const
{
return (m_refData != NULL && M_BITMAP->m_surface);
}
int wxBitmap::GetHeight() const
{
wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
int h = -1;
M_BITMAP->m_surface->GetSize(NULL, &h);
return h;
}
int wxBitmap::GetWidth() const
{
wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
int w = -1;
M_BITMAP->m_surface->GetSize(&w, NULL);
return w;
}
int wxBitmap::GetDepth() const
{
wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
return M_BITMAP->m_surface->GetDepth();
}
wxMask *wxBitmap::GetMask() const
{
wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
return M_BITMAP->m_mask;
}
void wxBitmap::SetMask(wxMask *mask)
{
wxCHECK_RET( Ok(), wxT("invalid bitmap") );
AllocExclusive();
delete M_BITMAP->m_mask;
M_BITMAP->m_mask = mask;
}
bool wxBitmap::CopyFromIcon(const wxIcon& icon)
{
*this = *((wxBitmap*)(&icon));
return true;
}
wxBitmap wxBitmap::GetSubBitmap(const wxRect& rect) const
{
wxCHECK_MSG( Ok() &&
rect.x >= 0 && rect.y >= 0 &&
rect.x+rect.width <= GetWidth() &&
rect.y+rect.height <= GetHeight(),
wxNullBitmap,
wxT("invalid bitmap or bitmap region") );
// NB: DirectFB subsurfaces share the same pixels buffer, so we must
// clone the obtained subsurface
DFBRectangle r = { rect.x, rect.y, rect.width, rect.height };
return wxBitmap(M_BITMAP->m_surface->GetSubSurface(&r)->Clone());
}
#warning "to common code"
bool wxBitmap::LoadFile(const wxString &name, wxBitmapType type)
{
UnRef();
wxBitmapHandler *handler = FindHandler(type);
if ( handler == NULL )
{
wxImage image;
if ( !image.LoadFile(name, type) || !image.Ok() )
{
wxLogError("no bitmap handler for type %d defined.", type);
return false;
}
else
{
*this = wxBitmap(image);
return true;
}
}
m_refData = new wxBitmapRefData();
return handler->LoadFile(this, name, type, -1, -1);
}
#warning "to common code"
bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, const wxPalette *palette) const
{
wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
wxBitmapHandler *handler = FindHandler(type);
if ( handler == NULL )
{
wxImage image = ConvertToImage();
#if wxUSE_PALETTE
if ( palette )
image.SetPalette(*palette);
#endif // wxUSE_PALETTE
if ( image.Ok() )
return image.SaveFile(filename, type);
else
{
wxLogError("no bitmap handler for type %d defined.", type);
return false;
}
}
return handler->SaveFile(this, filename, type, palette);
}
#if wxUSE_PALETTE
wxPalette *wxBitmap::GetPalette() const
{
wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
return M_BITMAP->m_palette;
}
void wxBitmap::SetPalette(const wxPalette& palette)
{
wxCHECK_RET( Ok(), wxT("invalid bitmap") );
wxCHECK_RET( GetDepth() > 1 && GetDepth() <= 8, wxT("cannot set palette for bitmap of this depth") );
AllocExclusive();
delete M_BITMAP->m_palette;
M_BITMAP->m_palette = NULL;
if ( !palette.Ok() ) return;
M_BITMAP->m_palette = new wxPalette(palette);
}
#endif // wxUSE_PALETTE
void wxBitmap::SetHeight(int height)
{
AllocExclusive();
wxFAIL_MSG( _T("SetHeight not implemented") );
}
void wxBitmap::SetWidth(int width)
{
AllocExclusive();
wxFAIL_MSG( _T("SetWidth not implemented") );
}
void wxBitmap::SetDepth(int depth)
{
AllocExclusive();
wxFAIL_MSG( _T("SetDepth not implemented") );
}
wxIDirectFBSurfacePtr wxBitmap::GetDirectFBSurface() const
{
wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
return M_BITMAP->m_surface;
}
wxObjectRefData *wxBitmap::CreateRefData() const
{
return new wxBitmapRefData;
}
wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *data) const
{
return new wxBitmapRefData(*(wxBitmapRefData *)data);
}
/*static*/
void wxBitmap::InitStandardHandlers()
{
// not wxBitmap handlers, we rely on wxImage
}