basic blitting implementation

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41274 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík 2006-09-18 11:20:58 +00:00
parent 11ea1abfa0
commit 5942996c94
5 changed files with 96 additions and 102 deletions

View File

@ -203,6 +203,10 @@ private:
void DoDrawSubBitmap(const wxBitmap &bmp, void DoDrawSubBitmap(const wxBitmap &bmp,
wxCoord x, wxCoord y, wxCoord w, wxCoord h, wxCoord x, wxCoord y, wxCoord w, wxCoord h,
wxCoord destx, wxCoord desty, int rop, bool useMask); wxCoord destx, wxCoord desty, int rop, bool useMask);
bool DoBlitFromSurface(const wxIDirectFBSurfacePtr& src,
wxCoord srcx, wxCoord srcy,
wxCoord w, wxCoord h,
wxCoord dstx, wxCoord dsty);
// selects colour into surface's state // selects colour into surface's state
void SelectColour(const wxColour& clr); void SelectColour(const wxColour& clr);

View File

@ -22,6 +22,13 @@ public:
virtual void SelectObject(const wxBitmap& bitmap); virtual void SelectObject(const wxBitmap& bitmap);
// implementation from now on:
wxBitmap GetSelectedObject() const { return m_bmp; }
private:
wxBitmap m_bmp;
DECLARE_DYNAMIC_CLASS(wxMemoryDC) DECLARE_DYNAMIC_CLASS(wxMemoryDC)
}; };

View File

@ -274,6 +274,14 @@ struct wxIDirectFBSurface : public wxDfbWrapper<IDirectFBSurface>
int x, int y) int x, int y)
{ return Check(m_ptr->Blit(m_ptr, source, source_rect, x, y)); } { return Check(m_ptr->Blit(m_ptr, source, source_rect, x, y)); }
bool StretchBlit(const wxIDirectFBSurfacePtr& source,
const DFBRectangle *source_rect,
const DFBRectangle *dest_rect)
{
return Check(m_ptr->StretchBlit(m_ptr, source->GetRaw(),
source_rect, dest_rect));
}
/// Returns bit depth used by the surface or -1 on error /// Returns bit depth used by the surface or -1 on error
int GetDepth(); int GetDepth();

View File

@ -391,7 +391,10 @@ void wxDC::SetLogicalFunction(int function)
{ {
wxCHECK_RET( Ok(), wxT("invalid dc") ); wxCHECK_RET( Ok(), wxT("invalid dc") );
wxFAIL_MSG( _T("SetLogicalFunction not implemented") ); // NB: we could also support XOR, but for blitting only (via DSBLIT_XOR);
// and possibly others via SetSrc/DstBlendFunction()
wxASSERT_MSG( function == wxCOPY,
_T("only wxCOPY logical function supported") );
m_logicalFunction = function; m_logicalFunction = function;
} }
@ -651,17 +654,21 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
int rop, bool useMask, int rop, bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask) wxCoord xsrcMask, wxCoord ysrcMask)
{ {
#warning "FIXME" wxCHECK_MSG( Ok(), false, _T("invalid dc") );
return false; wxCHECK_MSG( source, false, _T("invalid source dc") );
#if 0
wxCHECK_MSG( Ok(), false, wxT("invalid dc") ); // NB: we could also support XOR here (via DSBLIT_XOR)
wxCHECK_MSG( source, false, wxT("invalid source dc") ); // and possibly others via SetSrc/DstBlendFunction()
wxCHECK_MSG( rop == wxCOPY, false, _T("only wxCOPY function supported") );
// transform the source DC coords to the device ones // transform the source DC coords to the device ones
xsrc = source->LogicalToDeviceX(xsrc); xsrc = source->LogicalToDeviceX(xsrc);
ysrc = source->LogicalToDeviceY(ysrc); ysrc = source->LogicalToDeviceY(ysrc);
/* FIXME_MGL: use the mask origin when drawing transparently */ // FIXME_DFB: use the mask origin when drawing transparently
wxASSERT_MSG( xsrcMask == -1 && ysrcMask == -1,
_T("non-default source mask offset not implemented") );
#if 0
if (xsrcMask == -1 && ysrcMask == -1) if (xsrcMask == -1 && ysrcMask == -1)
{ {
xsrcMask = xsrc; ysrcMask = ysrc; xsrcMask = xsrc; ysrcMask = ysrc;
@ -671,32 +678,27 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
xsrcMask = source->LogicalToDeviceX(xsrcMask); xsrcMask = source->LogicalToDeviceX(xsrcMask);
ysrcMask = source->LogicalToDeviceY(ysrcMask); ysrcMask = source->LogicalToDeviceY(ysrcMask);
} }
#endif
CalcBoundingBox(xdest, ydest); wxMemoryDC *sourceAsMemDC = wxDynamicCast(source, wxMemoryDC);
CalcBoundingBox(xdest + width, ydest + height); if ( sourceAsMemDC )
/* scale/translate size and position */
wxCoord xx = XLOG2DEV(xdest);
wxCoord yy = YLOG2DEV(ydest);
wxCoord ww = XLOG2DEVREL(width);
wxCoord hh = YLOG2DEVREL(height);
if ( source->m_isMemDC )
{ {
wxMemoryDC *memDC = (wxMemoryDC*) source; DoDrawSubBitmap(sourceAsMemDC->GetSelectedObject(),
DoDrawSubBitmap(memDC->GetSelectedObject(), xsrc, ysrc, ww, hh, xsrc, ysrc,
xdest, ydest, rop, useMask); width, height,
xdest, ydest,
rop,
useMask);
} }
else else
{ {
m_MGLDC->makeCurrent(); // will go away with MGL6.0 return DoBlitFromSurface(source->GetDirectFBSurface(),
m_MGLDC->bitBlt(*source->GetMGLDC(), xsrc, ysrc,
xsrc, ysrc, xsrc + ww, ysrc + hh, width, height,
xx, yy, LogicalFunctionToMGLRop(rop)); xdest, ydest);
} }
return true; return true;
#endif
} }
void wxDC::DoDrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask) void wxDC::DoDrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask)
@ -704,10 +706,10 @@ void wxDC::DoDrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask)
wxCHECK_RET( Ok(), wxT("invalid dc") ); wxCHECK_RET( Ok(), wxT("invalid dc") );
wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") ); wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") );
wxCoord w = bmp.GetWidth(); DoDrawSubBitmap(bmp,
wxCoord h = bmp.GetHeight(); 0, 0, bmp.GetWidth(), bmp.GetHeight(),
x, y,
DoDrawSubBitmap(bmp, 0, 0, w, h, x, y, m_logicalFunction, useMask); m_logicalFunction, useMask);
} }
void wxDC::DoDrawIcon(const wxIcon& icon, wxCoord x, wxCoord y) void wxDC::DoDrawIcon(const wxIcon& icon, wxCoord x, wxCoord y)
@ -720,94 +722,65 @@ void wxDC::DoDrawSubBitmap(const wxBitmap &bmp,
wxCoord x, wxCoord y, wxCoord w, wxCoord h, wxCoord x, wxCoord y, wxCoord w, wxCoord h,
wxCoord destx, wxCoord desty, int rop, bool useMask) wxCoord destx, wxCoord desty, int rop, bool useMask)
{ {
#if 0
wxCHECK_RET( Ok(), wxT("invalid dc") ); wxCHECK_RET( Ok(), wxT("invalid dc") );
wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") ); wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") );
CalcBoundingBox(x, y); // NB: we could also support XOR here (via DSBLIT_XOR)
CalcBoundingBox(x + w, y + h); // and possibly others via SetSrc/DstBlendFunction()
wxCHECK_RET( rop == wxCOPY, _T("only wxCOPY function supported") );
wxCoord dx = XLOG2DEV(destx);
wxCoord dy = YLOG2DEV(desty);
wxCoord dw = XLOG2DEVREL(w);
wxCoord dh = YLOG2DEVREL(h);
m_MGLDC->makeCurrent(); // will go away with MGL6.0
bool useStretching = ((w != dw) || (h != dh));
bool putSection = (w != bmp.GetWidth() || h != bmp.GetHeight());
MGL_writeModeType mglRop = (MGL_writeModeType)LogicalFunctionToMGLRop(rop);
if ( bmp.GetDepth() == 1 ) if ( bmp.GetDepth() == 1 )
{ {
// Mono bitmaps are handled in special way -- all 1s are drawn in // Mono bitmaps are handled in special way -- all 1s are drawn in
// foreground colours, all 0s in background colour. // foreground colours, all 0s in background colour.
wxFAIL_MSG( _T("drawing mono bitmaps not implemented") );
((wxBitmap&)bmp).SetMonoPalette(m_textForegroundColour, m_textBackgroundColour); return;
} }
if ( useMask && bmp.GetMask() ) if ( useMask && bmp.GetMask() )
{ {
// Since MGL does not support masks directly (in MGL, mask is handled // FIXME_DFB: see MGL sources for a way to do it, but it's not directly
// in same way as in wxImage, i.e. there is one "key" color), we // applicable because DirectFB doesn't implement ROPs; OTOH,
// simulate masked bitblt in 6 steps (same as in MSW): // it has blitting modes that can be useful; finally, see
// // DFB's SetSrcBlendFunction() and SetSrcColorKey()
// 1. Create a temporary bitmap and copy the destination area into it. wxFAIL_MSG( _T("drawing bitmaps with masks not implemented") );
// 2. Copy the source area into the temporary bitmap using the return;
// specified logical function.
// 3. Set the masked area in the temporary bitmap to BLACK by ANDing
// the mask bitmap with the temp bitmap with the foreground colour
// set to WHITE and the bg colour set to BLACK.
// 4. Set the unmasked area in the destination area to BLACK by
// ANDing the mask bitmap with the destination area with the
// foreground colour set to BLACK and the background colour set
// to WHITE.
// 5. OR the temporary bitmap with the destination area.
// 6. Delete the temporary bitmap.
//
// This sequence of operations ensures that the source's transparent
// area need not be black, and logical functions are supported.
wxBitmap *mask = bmp.GetMask()->GetBitmap();
MGLMemoryDC *temp;
if ( GetDepth() <= 8 )
{
temp = new MGLMemoryDC(dw, dh, GetDepth(), NULL);
wxDC tempdc;
tempdc.SetMGLDC(temp, false);
tempdc.SetPalette(m_palette);
}
else
{
pixel_format_t pf;
m_MGLDC->getPixelFormat(pf);
temp = new MGLMemoryDC(dw, dh, GetDepth(), &pf);
}
wxCHECK_RET( temp->isValid(), wxT("cannot create temporary dc") );
temp->bitBlt(*m_MGLDC, dx, dy, dx + dw, dy + dh, 0, 0, MGL_REPLACE_MODE);
DoBitBlt(bmp, temp, x, y, w, h, 0, 0, dw, dh, mglRop,
useStretching, putSection);
mask->SetMonoPalette(wxColour(0,0,0), wxColour(255,255,255));
DoBitBlt(*mask, temp, x, y, w, h, 0, 0, dw, dh, MGL_R2_MASKSRC,
useStretching, putSection);
DoBitBlt(*mask, m_MGLDC, x, y, w, h, dx, dy, dw, dh, MGL_R2_MASKNOTSRC,
useStretching, putSection);
m_MGLDC->bitBlt(*temp, 0, 0, dw, dh, dx, dy, MGL_OR_MODE);
delete temp;
} }
DoBlitFromSurface(bmp.GetDirectFBSurface(),
x, y,
w, h,
destx, desty);
}
bool wxDC::DoBlitFromSurface(const wxIDirectFBSurfacePtr& src,
wxCoord srcx, wxCoord srcy,
wxCoord w, wxCoord h,
wxCoord dstx, wxCoord dsty)
{
CalcBoundingBox(dstx, dsty);
CalcBoundingBox(dstx + w, dsty + h);
DFBRectangle srcRect = { srcx, srcy, w, h };
DFBRectangle dstRect = { XLOG2DEV(dstx), YLOG2DEV(dsty),
XLOG2DEVREL(w), YLOG2DEVREL(h) };
wxIDirectFBSurfacePtr dst(m_surface);
// FIXME: this will have to be different in useMask case, see above
if ( !dst->SetBlittingFlags(DSBLIT_NOFX) )
return false;
if ( srcRect.w != dstRect.w || srcRect.h != dstRect.h )
{
// the bitmap is drawn stretched:
dst->StretchBlit(src, &srcRect, &dstRect);
}
else else
{ {
DoBitBlt(bmp, m_MGLDC, x, y, w, h, dx, dy, dw, dh, mglRop, // no stretching, size is preserved:
useStretching, putSection); dst->Blit(src, &srcRect, dstRect.x, dstRect.y);
} }
#endif
return true;
} }

View File

@ -49,6 +49,8 @@ wxMemoryDC::wxMemoryDC(wxDC *WXUNUSED(dc))
void wxMemoryDC::SelectObject(const wxBitmap& bitmap) void wxMemoryDC::SelectObject(const wxBitmap& bitmap)
{ {
m_bmp = bitmap;
if ( !bitmap.Ok() ) if ( !bitmap.Ok() )
{ {
// select the bitmap out of the DC // select the bitmap out of the DC