wxDC::StretchBlit() for wxMac and wxMSW (patch 1611973)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44892 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2007-03-18 15:32:27 +00:00
parent fa3b08caf1
commit e3b81044ee
12 changed files with 347 additions and 100 deletions

View File

@ -65,6 +65,7 @@ All:
All (GUI):
- Added wxDC::StretchBlit() for wxMac and wxMSW (Vince Harron)
- Added wxEventBlocker class (Francesco Montorsi).
- Added wxFile/DirPickerCtrl::Get/SetFile/DirName() (Francesco Montorsi).
- Added wxSizerFlags::Top() and Bottom().

View File

@ -108,7 +108,7 @@ See \helpref{wxMemoryDC}{wxmemorydc} for typical usage.
\wxheading{See also}
\helpref{wxMemoryDC}{wxmemorydc}, \helpref{wxBitmap}{wxbitmap}, \helpref{wxMask}{wxmask}
\helpref{wxDC::StretchBlit}{wxdcstretchblit}, \helpref{wxMemoryDC}{wxmemorydc}, \helpref{wxBitmap}{wxbitmap}, \helpref{wxMask}{wxmask}
\begin{comment}
@ -1198,3 +1198,84 @@ Message is a message to show while printing.
Starts a document page (only relevant when outputting to a printer).
\membersection{wxDC::StretchBlit}\label{wxdcstretchblit}
\func{bool}{StretchBlit}{\param{wxCoord}{ xdest}, \param{wxCoord}{ ydest}, \param{wxCoord}{ dstWidth}, \param{wxCoord}{ dstHeight},
\param{wxDC* }{source}, \param{wxCoord}{ xsrc}, \param{wxCoord}{ ysrc}, \param{wxCoord}{ srcWidth}, \param{wxCoord}{ srcHeight},
\param{int}{ logicalFunc = wxCOPY}, \param{bool }{useMask = false}, \param{wxCoord}{ xsrcMask = -1}, \param{wxCoord}{ ysrcMask = -1}}
Copy from a source DC to this DC, specifying the destination
coordinates, destination size, source DC, source coordinates,
size of source area to copy, logical function, whether to use a bitmap mask,
and mask source position.
\wxheading{Parameters}
\docparam{xdest}{Destination device context x position.}
\docparam{ydest}{Destination device context y position.}
\docparam{dstWidth}{Width of destination area.}
\docparam{dstHeight}{Height of destination area.}
\docparam{source}{Source device context.}
\docparam{xsrc}{Source device context x position.}
\docparam{ysrc}{Source device context y position.}
\docparam{srcWidth}{Width of source area to be copied.}
\docparam{srcHeight}{Height of source area to be copied.}
\docparam{logicalFunc}{Logical function to use: see \helpref{wxDC::SetLogicalFunction}{wxdcsetlogicalfunction}.}
\docparam{useMask}{If true, Blit does a transparent blit using the mask that is associated with the bitmap
selected into the source device context. The Windows implementation does the following if \texttt{MaskBlt} cannot be used:
\begin{enumerate}
\item Creates a temporary bitmap and copies the destination area into it.
\item Copies the source area into the temporary bitmap using the specified logical function.
\item Sets 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 background colour set to BLACK.
\item Sets 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.
\item ORs the temporary bitmap with the destination area.
\item Deletes the temporary bitmap.
\end{enumerate}
This sequence of operations ensures that the source's transparent area need not be black,
and logical functions are supported.
{\bf Note:} on Windows, blitting with masks can be speeded up considerably by compiling
wxWidgets with the \texttt{wxUSE\_DC\_CACHE} option enabled. You can also influence whether \texttt{MaskBlt}
or the explicit mask blitting code above is used, by using \helpref{wxSystemOptions}{wxsystemoptions} and
setting the {\bf no-maskblt} option to 1.
}
\docparam{xsrcMask}{Source x position on the mask. If both xsrcMask and ysrcMask are -1, xsrc and ysrc
will be assumed for the mask source position. Currently only implemented on Windows.}
\docparam{ysrcMask}{Source y position on the mask. If both xsrcMask and ysrcMask are -1, xsrc and ysrc
will be assumed for the mask source position. Currently only implemented on Windows.}
\wxheading{Remarks}
There is partial support for Blit in wxPostScriptDC, under X.
wxDC::StretchBlit is only implemented under wxMAC and wxMSW.
See \helpref{wxMemoryDC}{wxmemorydc} for typical usage.
\newsince{2.9.0}
\wxheading{See also}
\helpref{wxDC::Blit}{wxdcblit}, \helpref{wxMemoryDC}{wxmemorydc}, \helpref{wxBitmap}{wxbitmap}, \helpref{wxMask}{wxmask}

View File

@ -314,6 +314,25 @@ public:
source, srcPt.x, srcPt.y, rop, useMask, srcPtMask.x, srcPtMask.y);
}
bool StretchBlit(wxCoord dstX, wxCoord dstY,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord srcX, wxCoord srcY,
wxCoord srcWidth, wxCoord srcHeight,
int rop = wxCOPY, bool useMask = false,
wxCoord srcMaskX = wxDefaultCoord, wxCoord srcMaskY = wxDefaultCoord)
{
return DoStretchBlit(dstX, dstY, dstWidth, dstHeight,
source, srcX, srcY, srcWidth, srcHeight, rop, useMask, srcMaskX, srcMaskY);
}
bool StretchBlit(const wxPoint& dstPt, const wxSize& dstSize,
wxDC *source, const wxPoint& srcPt, const wxSize& srcSize,
int rop = wxCOPY, bool useMask = false, const wxPoint& srcMaskPt = wxDefaultPosition)
{
return DoStretchBlit(dstPt.x, dstPt.y, dstSize.x, dstSize.y,
source, srcPt.x, srcPt.y, srcSize.x, srcSize.y, rop, useMask, srcMaskPt.x, srcMaskPt.y);
}
wxBitmap GetAsBitmap(const wxRect *subrect = (const wxRect *) NULL) const
{
return DoGetAsBitmap(subrect);
@ -723,10 +742,25 @@ protected:
virtual bool DoBlit(wxCoord xdest, wxCoord ydest,
wxCoord width, wxCoord height,
wxDC *source, wxCoord xsrc, wxCoord ysrc,
int rop = wxCOPY, bool useMask = false, wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord) = 0;
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
int rop = wxCOPY,
bool useMask = false,
wxCoord xsrcMask = wxDefaultCoord,
wxCoord ysrcMask = wxDefaultCoord) = 0;
virtual wxBitmap DoGetAsBitmap(const wxRect *WXUNUSED(subrect)) const { return wxNullBitmap; }
virtual bool DoStretchBlit(wxCoord xdest, wxCoord ydest,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
wxCoord srcWidth, wxCoord srcHeight,
int rop = wxCOPY,
bool useMask = false,
wxCoord xsrcMask = wxDefaultCoord,
wxCoord ysrcMask = wxDefaultCoord);
virtual wxBitmap DoGetAsBitmap(const wxRect *WXUNUSED(subrect)) const
{ return wxNullBitmap; }
virtual void DoGetSize(int *width, int *height) const = 0;
virtual void DoGetSizeMM(int* width, int* height) const = 0;

View File

@ -145,6 +145,14 @@ protected:
wxDC *source, wxCoord xsrc, wxCoord ysrc,
int rop = wxCOPY, bool useMask = false, wxCoord xsrcMask = -1, wxCoord ysrcMask = -1);
virtual bool DoStretchBlit(wxCoord xdest, wxCoord ydest,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
wxCoord srcWidth, wxCoord srcHeight,
int rop = wxCOPY, bool useMask = false,
wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord);
virtual void DoGetSize(int *,int *) const;
virtual void DoGetSizeMM(int* width, int* height) const;

View File

@ -255,6 +255,14 @@ protected:
wxDC *source, wxCoord xsrc, wxCoord ysrc,
int rop = wxCOPY, bool useMask = false, wxCoord xsrcMask = -1, wxCoord ysrcMask = -1);
virtual bool DoStretchBlit(wxCoord xdest, wxCoord ydest,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
wxCoord srcWidth, wxCoord srcHeight,
int rop = wxCOPY, bool useMask = false,
wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord);
// this is gnarly - we can't even call this function DoSetClippingRegion()
// because of virtual function hiding

View File

@ -214,6 +214,14 @@ protected:
wxDC *source, wxCoord xsrc, wxCoord ysrc,
int rop = wxCOPY, bool useMask = false, wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord);
virtual bool DoStretchBlit(wxCoord xdest, wxCoord ydest,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
wxCoord srcWidth, wxCoord srcHeight,
int rop = wxCOPY, bool useMask = false,
wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord);
// this is gnarly - we can't even call this function DoSetClippingRegion()
// because of virtual function hiding
virtual void DoSetClippingRegionAsRegion(const wxRegion& region);

View File

@ -70,6 +70,7 @@ enum ScreenToShow
Show_Brushes,
Show_Polygons,
Show_Mask,
Show_Mask_Stretch,
Show_Ops,
Show_Regions,
Show_Circles,
@ -178,11 +179,17 @@ public:
#endif
protected:
enum DrawMode
{
Draw_Normal,
Draw_Stretch
};
void DrawTestLines( int x, int y, int width, wxDC &dc );
void DrawTestPoly(wxDC& dc);
void DrawTestBrushes(wxDC& dc);
void DrawText(wxDC& dc);
void DrawImages(wxDC& dc);
void DrawImages(wxDC& dc, DrawMode mode);
void DrawWithLogicalOps(wxDC& dc);
#if wxUSE_GRAPHICS_CONTEXT
void DrawAlpha(wxDC& dc);
@ -227,6 +234,7 @@ enum
File_ShowBrushes,
File_ShowPolygons,
File_ShowMask,
File_ShowMaskStretch,
File_ShowOps,
File_ShowRegions,
File_ShowCircles,
@ -310,6 +318,7 @@ bool MyApp::LoadImages()
wxPathList pathList;
pathList.Add(_T("."));
pathList.Add(_T(".."));
pathList.Add(_T("../.."));
wxString path = pathList.FindValidPath(_T("pat4.bmp"));
if ( !path )
@ -835,7 +844,7 @@ static const struct
{ wxT("wxXOR"), wxXOR },
};
void MyCanvas::DrawImages(wxDC& dc)
void MyCanvas::DrawImages(wxDC& dc, DrawMode mode)
{
dc.DrawText(_T("original image"), 0, 0);
dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0);
@ -857,9 +866,17 @@ void MyCanvas::DrawImages(wxDC& dc)
dc.DrawText(rasterOperations[n].name, x, y - 20);
memDC.SelectObject(*gs_bmpWithColMask);
if ( mode == Draw_Stretch )
{
dc.StretchBlit(x, y, cx, cy, &memDC, 0, 0, cx/2, cy/2,
rasterOperations[n].rop, true);
}
else
{
dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true);
}
}
}
void MyCanvas::DrawWithLogicalOps(wxDC& dc)
{
@ -1280,7 +1297,11 @@ void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
break;
case Show_Mask:
DrawImages(dc);
DrawImages(dc, Draw_Normal);
break;
case Show_Mask_Stretch:
DrawImages(dc, Draw_Stretch);
break;
case Show_Ops:
@ -1355,6 +1376,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
menuFile->Append(File_ShowBrushes, _T("&Brushes screen\tF4"));
menuFile->Append(File_ShowPolygons, _T("&Polygons screen\tF5"));
menuFile->Append(File_ShowMask, _T("&Mask screen\tF6"));
menuFile->Append(File_ShowMaskStretch, _T("1/&2 scaled mask\tShift-F6"));
menuFile->Append(File_ShowOps, _T("&ROP screen\tF7"));
menuFile->Append(File_ShowRegions, _T("Re&gions screen\tF8"));
menuFile->Append(File_ShowCircles, _T("&Circles screen\tF9"));

View File

@ -78,6 +78,27 @@ void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1,
CalcBoundingBox(x2, y2);
}
// ----------------------------------------------------------------------------
// stubs for functions not implemented in all ports
// ----------------------------------------------------------------------------
bool
wxDCBase::DoStretchBlit(wxCoord xdest, wxCoord ydest,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
wxCoord WXUNUSED(srcWidth), wxCoord WXUNUSED(srcHeight),
int rop,
bool useMask,
wxCoord xsrcMask,
wxCoord ysrcMask)
{
// temporary default implementation to avoid breaking platforms that don't
// have DoStretchBlit
return DoBlit(xdest, ydest, dstWidth, dstHeight, source,
xsrc, ysrc, rop, useMask, xsrcMask, ysrcMask);
}
// ----------------------------------------------------------------------------
// line/polygons
// ----------------------------------------------------------------------------
@ -1156,4 +1177,4 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
} // not iUseAngles
} // CalculateEllipticPoints
#endif
#endif // __WXWINCE__

View File

@ -718,11 +718,22 @@ bool wxGCDC::CanDrawBitmap() const
bool wxGCDC::DoBlit(
wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool WXUNUSED(useMask),
wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask )
{
wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid DC") );
wxCHECK_MSG( source->Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid source DC") );
return DoStretchBlit( xdest, ydest, width, height,
source, xsrc, ysrc, width, height, logical_func, useMask,
xsrcMask,ysrcMask );
}
bool wxGCDC::DoStretchBlit(
wxCoord xdest, wxCoord ydest, wxCoord dstWidth, wxCoord dstHeight,
wxDC *source, wxCoord xsrc, wxCoord ysrc, wxCoord srcWidth, wxCoord srcHeight,
int logical_func , bool WXUNUSED(useMask),
wxCoord xsrcMask, wxCoord ysrcMask )
{
wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid DC") );
wxCHECK_MSG( source->Ok(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid source DC") );
if ( logical_func == wxNO_OP )
return true;
@ -740,8 +751,8 @@ bool wxGCDC::DoBlit(
wxRect subrect(source->LogicalToDeviceX(xsrc),
source->LogicalToDeviceY(ysrc),
source->LogicalToDeviceXRel(width),
source->LogicalToDeviceYRel(height));
source->LogicalToDeviceXRel(srcWidth),
source->LogicalToDeviceYRel(srcHeight));
// if needed clip the subrect down to the size of the source DC
wxCoord sw, sh;
@ -758,8 +769,7 @@ bool wxGCDC::DoBlit(
if ( blit.Ok() )
{
m_graphicContext->DrawBitmap( blit, xdest, ydest,
wxMin(width, blit.GetWidth()),
wxMin(height, blit.GetHeight()));
dstWidth, dstHeight);
}
else
{

View File

@ -1175,12 +1175,26 @@ bool wxDC::CanDrawBitmap(void) const
return true ;
}
bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord dstWidth, wxCoord dstHeight,
wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask )
{
wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit - invalid DC"));
wxCHECK_MSG(source->Ok(), false, wxT("wxDC::DoBlit - invalid source DC"));
return DoStretchBlit( xdest, ydest, dstWidth, dstHeight,
source, xsrc, ysrc, dstWidth, dstHeight,
logical_func, useMask,
xsrcMask, ysrcMask );
}
bool wxDC::DoStretchBlit(wxCoord xdest, wxCoord ydest,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
wxCoord srcWidth, wxCoord srcHeight,
int logical_func = wxCOPY, bool useMask = false,
wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord);
{
wxCHECK_MSG(Ok(), false, wxT("wxDC::DoStretchBlit - invalid DC"));
wxCHECK_MSG(source->Ok(), false, wxT("wxDC::DoStretchBlit - invalid source DC"));
if ( logical_func == wxNO_OP )
return true ;
@ -1198,12 +1212,12 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
Rect srcrect , dstrect ;
srcrect.top = source->YLOG2DEVMAC(ysrc) ;
srcrect.left = source->XLOG2DEVMAC(xsrc) ;
srcrect.right = source->XLOG2DEVMAC(xsrc + width ) ;
srcrect.bottom = source->YLOG2DEVMAC(ysrc + height) ;
srcrect.right = source->XLOG2DEVMAC(xsrc + srcWidth ) ;
srcrect.bottom = source->YLOG2DEVMAC(ysrc + srcHeight) ;
dstrect.top = YLOG2DEVMAC(ydest) ;
dstrect.left = XLOG2DEVMAC(xdest) ;
dstrect.bottom = YLOG2DEVMAC(ydest + height ) ;
dstrect.right = XLOG2DEVMAC(xdest + width ) ;
dstrect.bottom = YLOG2DEVMAC(ydest + dstHeight ) ;
dstrect.right = XLOG2DEVMAC(xdest + dstWidth ) ;
short mode = kUnsupportedMode ;
bool invertDestinationFirst = false ;

View File

@ -2021,8 +2021,22 @@ bool wxDC::DoBlit(
wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask )
{
wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoBlit - invalid DC") );
wxCHECK_MSG( source->Ok(), false, wxT("wxDC(cg)::DoBlit - invalid source DC") );
return DoStretchBlit( xdest, ydest, width, height,
source, xsrc, ysrc, width, height,
logical_func, useMask,
xsrcMask, ysrcMask );
}
bool wxDC::DoStretchBlit(wxCoord xdest, wxCoord ydest,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
wxCoord srcWidth, wxCoord srcHeight,
int logical_func = wxCOPY, bool useMask = false,
wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord);
{
wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoStretchBlit - invalid DC") );
wxCHECK_MSG( source->Ok(), false, wxT("wxDC(cg)::DoStretchBlit - invalid source DC") );
if ( logical_func == wxNO_OP )
return true ;
@ -2035,13 +2049,13 @@ bool wxDC::DoBlit(
wxCoord yysrc = source->YLOG2DEVMAC(ysrc) ;
wxCoord xxsrc = source->XLOG2DEVMAC(xsrc) ;
wxCoord wwsrc = source->XLOG2DEVREL(width) ;
wxCoord hhsrc = source->YLOG2DEVREL(height) ;
wxCoord wwsrc = source->XLOG2DEVREL(srcWidth) ;
wxCoord hhsrc = source->YLOG2DEVREL(srcHeight) ;
wxCoord yydest = YLOG2DEVMAC(ydest) ;
wxCoord xxdest = XLOG2DEVMAC(xdest) ;
wxCoord wwdest = XLOG2DEVREL(width) ;
wxCoord hhdest = YLOG2DEVREL(height) ;
wxCoord wwdest = XLOG2DEVREL(dstWidth) ;
wxCoord hhdest = YLOG2DEVREL(dstHeight) ;
wxMemoryDC* memdc = dynamic_cast<wxMemoryDC*>(source) ;
if ( memdc && logical_func == wxCOPY )

View File

@ -130,16 +130,21 @@ static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
// return true if we could draw the bitmap in one way or the other, false
// otherwise
static bool AlphaBlt(HDC hdcDst,
int x, int y, int w, int h,
int srcX, int srcY, HDC hdcSrc,
const wxBitmap& bmpSrc);
int x, int y, int dstWidth, int dstHeight,
int srcX, int srcY,
int srcWidth, int srcHeight,
HDC hdcSrc,
const wxBitmap& bmp);
#ifdef wxHAVE_RAW_BITMAP
// our (limited) AlphaBlend() replacement for Windows versions not providing it
static void
wxAlphaBlend(HDC hdcDst, int x, int y, int w, int h,
int srcX, int srcY, const wxBitmap& bmp);
wxAlphaBlend(HDC hdcDst, int xDst, int yDst,
int dstWidth, int dstHeight,
int srcX, int srcY,
int srcWidth, int srcHeight,
const wxBitmap& bmpSrc);
#endif // wxHAVE_RAW_BITMAP
@ -1183,7 +1188,7 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask
MemoryHDC hdcMem;
SelectInHDC select(hdcMem, GetHbitmapOf(bmp));
if ( AlphaBlt(GetHdc(), x, y, width, height, 0, 0, hdcMem, bmp) )
if ( AlphaBlt(GetHdc(), x, y, width, height, 0, 0, width, height, hdcMem, bmp) )
return;
}
@ -2046,10 +2051,21 @@ wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
// ---------------------------------------------------------------------------
// bit blit
// ---------------------------------------------------------------------------
bool wxDC::DoBlit(wxCoord dstX, wxCoord dstY,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord srcX, wxCoord srcY,
int rop, bool useMask,
wxCoord srcMaskX, wxCoord srcMaskY)
{
return DoStretchBlit(dstX, dstY, dstWidth, dstHeight, source, srcX, srcY, dstWidth, dstHeight, rop, useMask, srcMaskX, srcMaskY);
}
bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
wxCoord width, wxCoord height,
wxDC *source, wxCoord xsrc, wxCoord ysrc,
bool wxDC::DoStretchBlit(wxCoord xdest, wxCoord ydest,
wxCoord dstWidth, wxCoord dstHeight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
wxCoord srcWidth, wxCoord srcHeight,
int rop, bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask)
{
@ -2063,8 +2079,8 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
if ( bmpSrc.Ok() && (bmpSrc.HasAlpha() ||
(m_selectedBitmap.Ok() && m_selectedBitmap.HasAlpha())) )
{
if ( AlphaBlt(GetHdc(), xdest, ydest, width, height,
xsrc, ysrc, GetHdcOf(*source), bmpSrc) )
if ( AlphaBlt(GetHdc(), xdest, ydest, dstWidth, dstHeight,
xsrc, ysrc, srcWidth, srcHeight, GetHdcOf(*source), bmpSrc) )
return true;
}
@ -2137,11 +2153,13 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
#if wxUSE_SYSTEM_OPTIONS
if (wxSystemOptions::GetOptionInt(wxT("no-maskblt")) == 0)
#endif
{
if ( dstWidth == srcWidth && dstHeight == srcHeight )
{
success = ::MaskBlt
(
GetHdc(),
xdest, ydest, width, height,
xdest, ydest, dstWidth, dstHeight,
GetHdcOf(*source),
xsrc, ysrc,
(HBITMAP)mask->GetMaskBitmap(),
@ -2149,6 +2167,7 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
MAKEROP4(dwRop, DSTCOPY)
) != 0;
}
}
if ( !success )
#endif // Win32
@ -2167,55 +2186,59 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
dc_buffer = (HDC) dcCacheEntry2->m_dc;
wxDCCacheEntry* bitmapCacheEntry = FindBitmapInCache(GetHDC(),
width, height);
dstWidth, dstHeight);
buffer_bmap = (HBITMAP) bitmapCacheEntry->m_bitmap;
#else // !wxUSE_DC_CACHEING
// create a temp buffer bitmap and DCs to access it and the mask
dc_mask = ::CreateCompatibleDC(GetHdcOf(*source));
dc_buffer = ::CreateCompatibleDC(GetHdc());
buffer_bmap = ::CreateCompatibleBitmap(GetHdc(), width, height);
buffer_bmap = ::CreateCompatibleBitmap(GetHdc(), dstWidth, dstHeight);
#endif // wxUSE_DC_CACHEING/!wxUSE_DC_CACHEING
HGDIOBJ hOldMaskBitmap = ::SelectObject(dc_mask, (HBITMAP) mask->GetMaskBitmap());
HGDIOBJ hOldBufferBitmap = ::SelectObject(dc_buffer, buffer_bmap);
// copy dest to buffer
if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
if ( !::BitBlt(dc_buffer, 0, 0, (int)dstWidth, (int)dstHeight,
GetHdc(), xdest, ydest, SRCCOPY) )
{
wxLogLastError(wxT("BitBlt"));
}
#ifndef __WXWINCE__
StretchBltModeChanger changeMode(dc_buffer, COLORONCOLOR);
#endif
// copy src to buffer using selected raster op
if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
GetHdcOf(*source), xsrc, ysrc, dwRop) )
if ( !::StretchBlt(dc_buffer, 0, 0, (int)dstWidth, (int)dstHeight,
GetHdcOf(*source), xsrc, ysrc, srcWidth, srcHeight, dwRop) )
{
wxLogLastError(wxT("BitBlt"));
wxLogLastError(wxT("StretchBlt"));
}
// set masked area in buffer to BLACK (pixel value 0)
COLORREF prevBkCol = ::SetBkColor(GetHdc(), RGB(255, 255, 255));
COLORREF prevCol = ::SetTextColor(GetHdc(), RGB(0, 0, 0));
if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
dc_mask, xsrcMask, ysrcMask, SRCAND) )
if ( !::StretchBlt(dc_buffer, 0, 0, (int)dstWidth, (int)dstHeight,
dc_mask, xsrcMask, ysrcMask, srcWidth, srcHeight, SRCAND) )
{
wxLogLastError(wxT("BitBlt"));
wxLogLastError(wxT("StretchBlt"));
}
// set unmasked area in dest to BLACK
::SetBkColor(GetHdc(), RGB(0, 0, 0));
::SetTextColor(GetHdc(), RGB(255, 255, 255));
if ( !::BitBlt(GetHdc(), xdest, ydest, (int)width, (int)height,
dc_mask, xsrcMask, ysrcMask, SRCAND) )
if ( !::StretchBlt(GetHdc(), xdest, ydest, (int)dstWidth, (int)dstHeight,
dc_mask, xsrcMask, ysrcMask, srcWidth, srcHeight, SRCAND) )
{
wxLogLastError(wxT("BitBlt"));
wxLogLastError(wxT("StretchBlt"));
}
::SetBkColor(GetHdc(), prevBkCol); // restore colours to original values
::SetTextColor(GetHdc(), prevCol);
// OR buffer to dest
success = ::BitBlt(GetHdc(), xdest, ydest,
(int)width, (int)height,
(int)dstWidth, (int)dstHeight,
dc_buffer, 0, 0, SRCPAINT) != 0;
if ( !success )
{
@ -2260,14 +2283,14 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
if ( hDIB > 0 )
{
// reflect ysrc
ysrc = hDIB - (ysrc + height);
ysrc = hDIB - (ysrc + dstHeight);
}
if ( ::StretchDIBits(GetHdc(),
xdest, ydest,
width, height,
dstWidth, dstHeight,
xsrc, ysrc,
width, height,
srcWidth, srcHeight,
ds.dsBm.bmBits,
(LPBITMAPINFO)&ds.dsBmih,
DIB_RGB_COLORS,
@ -2298,9 +2321,9 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
if ( !::StretchBlt
(
GetHdc(),
xdest, ydest, width, height,
xdest, ydest, dstWidth, dstHeight,
GetHdcOf(*source),
xsrc, ysrc, width, height,
xsrc, ysrc, srcWidth, srcHeight,
dwRop
) )
{
@ -2318,7 +2341,7 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
(
GetHdc(),
xdest, ydest,
(int)width, (int)height,
(int)dstWidth, (int)dstHeight,
GetHdcOf(*source),
xsrc, ysrc,
dwRop
@ -2540,8 +2563,10 @@ IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
// ----------------------------------------------------------------------------
static bool AlphaBlt(HDC hdcDst,
int x, int y, int width, int height,
int srcX, int srcY, HDC hdcSrc,
int x, int y, int dstWidth, int dstHeight,
int srcX, int srcY,
int srcWidth, int srcHeight,
HDC hdcSrc,
const wxBitmap& bmp)
{
wxASSERT_MSG( bmp.Ok() && bmp.HasAlpha(), _T("AlphaBlt(): invalid bitmap") );
@ -2564,8 +2589,8 @@ static bool AlphaBlt(HDC hdcDst,
bf.SourceConstantAlpha = 0xff;
bf.AlphaFormat = AC_SRC_ALPHA;
if ( pfnAlphaBlend(hdcDst, x, y, width, height,
hdcSrc, srcX, srcY, width, height,
if ( pfnAlphaBlend(hdcDst, x, y, dstWidth, dstHeight,
hdcSrc, srcX, srcY, srcWidth, srcHeight,
bf) )
{
// skip wxAlphaBlend() call below
@ -2581,7 +2606,7 @@ static bool AlphaBlt(HDC hdcDst,
// AlphaBlend() unavailable of failed: use our own (probably much slower)
// implementation
#ifdef wxHAVE_RAW_BITMAP
wxAlphaBlend(hdcDst, x, y, width, height, srcX, srcY, bmp);
wxAlphaBlend(hdcDst, x, y, dstWidth, dstHeight, srcX, srcY, srcWidth, srcHeight, bmp);
return true;
#else // !wxHAVE_RAW_BITMAP
@ -2598,15 +2623,17 @@ static bool AlphaBlt(HDC hdcDst,
static void
wxAlphaBlend(HDC hdcDst, int xDst, int yDst,
int w, int h,
int srcX, int srcY, const wxBitmap& bmpSrc)
int dstWidth, int dstHeight,
int srcX, int srcY,
int srcWidth, int srcHeight,
const wxBitmap& bmpSrc)
{
// get the destination DC pixels
wxBitmap bmpDst(w, h, 32 /* force creating RGBA DIB */);
wxBitmap bmpDst(dstWidth, dstHeight, 32 /* force creating RGBA DIB */);
MemoryHDC hdcMem;
SelectInHDC select(hdcMem, GetHbitmapOf(bmpDst));
if ( !::BitBlt(hdcMem, 0, 0, w, h, hdcDst, xDst, yDst, SRCCOPY) )
if ( !::BitBlt(hdcMem, 0, 0, dstWidth, dstHeight, hdcDst, xDst, yDst, SRCCOPY) )
{
wxLogLastError(_T("BitBlt"));
}
@ -2621,15 +2648,17 @@ wxAlphaBlend(HDC hdcDst, int xDst, int yDst,
wxAlphaPixelData::Iterator pDst(dataDst),
pSrc(dataSrc);
pSrc.Offset(dataSrc, srcX, srcY);
for ( int y = 0; y < h; y++ )
for ( int y = 0; y < dstHeight; y++ )
{
wxAlphaPixelData::Iterator pDstRowStart = pDst,
pSrcRowStart = pSrc;
wxAlphaPixelData::Iterator pDstRowStart = pDst;
for ( int x = 0; x < w; x++ )
for ( int x = 0; x < dstWidth; x++ )
{
// source is point sampled, Alpha StretchBlit is ugly on Win95
// (but does not impact performance)
pSrc.MoveTo(dataSrc, srcX + (srcWidth*x/dstWidth), srcY + (srcHeight*y/dstHeight));
// note that source bitmap uses premultiplied alpha (as required by
// the real AlphaBlend)
const unsigned beta = 255 - pSrc.Alpha();
@ -2639,17 +2668,14 @@ wxAlphaBlend(HDC hdcDst, int xDst, int yDst,
pDst.Green() = pSrc.Green() + (beta * pDst.Green() + 127) / 255;
++pDst;
++pSrc;
}
pDst = pDstRowStart;
pSrc = pSrcRowStart;
pDst.OffsetY(dataDst, 1);
pSrc.OffsetY(dataSrc, 1);
}
// and finally blit them back to the destination DC
if ( !::BitBlt(hdcDst, xDst, yDst, w, h, hdcMem, 0, 0, SRCCOPY) )
if ( !::BitBlt(hdcDst, xDst, yDst, dstWidth, dstHeight, hdcMem, 0, 0, SRCCOPY) )
{
wxLogLastError(_T("BitBlt"));
}