diff --git a/docs/changes.txt b/docs/changes.txt index 212e6e800c..4fe7ed481b 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -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(). diff --git a/docs/latex/wx/dc.tex b/docs/latex/wx/dc.tex index 5f57bfbac9..cffeac284a 100644 --- a/docs/latex/wx/dc.tex +++ b/docs/latex/wx/dc.tex @@ -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} + diff --git a/include/wx/dc.h b/include/wx/dc.h index 67fd8f48c8..a846442f68 100644 --- a/include/wx/dc.h +++ b/include/wx/dc.h @@ -313,7 +313,26 @@ public: return DoBlit(destPt.x, destPt.y, sz.x, sz.y, 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; diff --git a/include/wx/dcgraph.h b/include/wx/dcgraph.h index 9115ec0af4..35fd3f9b14 100755 --- a/include/wx/dcgraph.h +++ b/include/wx/dcgraph.h @@ -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; diff --git a/include/wx/mac/carbon/dc.h b/include/wx/mac/carbon/dc.h index 161997dd71..b0e83d67d2 100644 --- a/include/wx/mac/carbon/dc.h +++ b/include/wx/mac/carbon/dc.h @@ -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 diff --git a/include/wx/msw/dc.h b/include/wx/msw/dc.h index 0ab2cc622e..9e6f7fcab8 100644 --- a/include/wx/msw/dc.h +++ b/include/wx/msw/dc.h @@ -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); diff --git a/samples/drawing/drawing.cpp b/samples/drawing/drawing.cpp index 95fadd09ba..2c217f8826 100644 --- a/samples/drawing/drawing.cpp +++ b/samples/drawing/drawing.cpp @@ -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,7 +866,15 @@ void MyCanvas::DrawImages(wxDC& dc) dc.DrawText(rasterOperations[n].name, x, y - 20); memDC.SelectObject(*gs_bmpWithColMask); - dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true); + 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); + } } } @@ -912,32 +929,32 @@ void MyCanvas::DrawAlpha(wxDC& dc) wxDouble margin = 20 ; wxDouble width = 180 ; wxDouble radius = 30 ; - + dc.SetPen( wxPen( wxColour( 128, 0, 0, 255 ),12, wxSOLID)); dc.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID)); - + wxRect r(margin,margin+width*0.66,width,width) ; - + dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ; - + dc.SetPen( wxPen( wxColour( 0, 0, 128, 255 ),12, wxSOLID)); dc.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID)); - + r.Offset( width * 0.8 , - width * 0.66 ) ; - + dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ; - + dc.SetPen( wxPen( wxColour( 128, 128, 0, 255 ),12, wxSOLID)); dc.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID)); r.Offset( width * 0.8 , width *0.5 ) ; - + dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ; - + dc.SetPen( *wxTRANSPARENT_PEN ) ; dc.SetBrush( wxBrush( wxColour(255,255,128,128) ) ); dc.DrawRoundedRectangle( 0 , margin + width / 2 , width * 3 , 100 , radius) ; - + dc.SetTextForeground( wxColour(255,255,0,128) ); dc.SetFont( wxFont( 40, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL ) ); dc.DrawText( wxT("Hello!"), 120, 80 ); @@ -976,9 +993,9 @@ void MyCanvas::DrawCircles(wxDC& dc) dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180); dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270); dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360); - + // same as above, just transparent brush - + dc.SetPen( *wxRED_PEN ); dc.SetBrush( *wxTRANSPARENT_BRUSH ); @@ -1005,7 +1022,7 @@ void MyCanvas::DrawCircles(wxDC& dc) dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180); dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270); dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360); - + } void MyCanvas::DrawSplines(wxDC& dc) @@ -1280,13 +1297,17 @@ 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: DrawWithLogicalOps(dc); break; - + #if wxUSE_GRAPHICS_CONTEXT case Show_Alpha: DrawAlpha(dc); @@ -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")); diff --git a/src/common/dcbase.cpp b/src/common/dcbase.cpp index 9cffc3896a..0bdd8d06ef 100644 --- a/src/common/dcbase.cpp +++ b/src/common/dcbase.cpp @@ -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 // ---------------------------------------------------------------------------- @@ -734,7 +755,7 @@ void wxDCBase::DoGradientFillLinear(const wxRect& rect, else nB = nB1 + (nB2-nB1)*(w-x)/w; - wxColour colour(nR,nG,nB); + wxColour colour(nR,nG,nB); SetPen(wxPen(colour, 1, wxSOLID)); SetBrush(wxBrush(colour)); if(nDirection == wxEAST) @@ -771,7 +792,7 @@ void wxDCBase::DoGradientFillLinear(const wxRect& rect, else nB = nB1 + (nB2-nB1)*(w-y)/w; - wxColour colour(nR,nG,nB); + wxColour colour(nR,nG,nB); SetPen(wxPen(colour, 1, wxSOLID)); SetBrush(wxBrush(colour)); if(nDirection == wxNORTH) @@ -1156,4 +1177,4 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, } // not iUseAngles } // CalculateEllipticPoints -#endif +#endif // __WXWINCE__ diff --git a/src/common/dcgraph.cpp b/src/common/dcgraph.cpp index 993cccf3db..40ff9d38d9 100644 --- a/src/common/dcgraph.cpp +++ b/src/common/dcgraph.cpp @@ -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 { diff --git a/src/mac/carbon/dc.cpp b/src/mac/carbon/dc.cpp index 6ead8a9bbc..9a789f821f 100644 --- a/src/mac/carbon/dc.cpp +++ b/src/mac/carbon/dc.cpp @@ -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 ; diff --git a/src/mac/carbon/dccg.cpp b/src/mac/carbon/dccg.cpp index 4cd27e7247..abd909dede 100755 --- a/src/mac/carbon/dccg.cpp +++ b/src/mac/carbon/dccg.cpp @@ -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(source) ; if ( memdc && logical_func == wxCOPY ) diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index dd4750f6a0..344d9105c3 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -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,12 +2051,23 @@ wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const // --------------------------------------------------------------------------- // bit blit // --------------------------------------------------------------------------- - -bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, - wxCoord width, wxCoord height, - wxDC *source, wxCoord xsrc, wxCoord ysrc, +bool wxDC::DoBlit(wxCoord dstX, wxCoord dstY, + wxCoord dstWidth, wxCoord dstHeight, + wxDC *source, + wxCoord srcX, wxCoord srcY, int rop, bool useMask, - wxCoord xsrcMask, wxCoord ysrcMask) + wxCoord srcMaskX, wxCoord srcMaskY) +{ + return DoStretchBlit(dstX, dstY, dstWidth, dstHeight, source, srcX, srcY, dstWidth, dstHeight, rop, useMask, srcMaskX, srcMaskY); +} + +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) { wxCHECK_MSG( source, false, _T("wxDC::Blit(): NULL wxDC pointer") ); @@ -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; } @@ -2138,16 +2154,19 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, if (wxSystemOptions::GetOptionInt(wxT("no-maskblt")) == 0) #endif { - success = ::MaskBlt - ( + if ( dstWidth == srcWidth && dstHeight == srcHeight ) + { + success = ::MaskBlt + ( GetHdc(), - xdest, ydest, width, height, + xdest, ydest, dstWidth, dstHeight, GetHdcOf(*source), xsrc, ysrc, (HBITMAP)mask->GetMaskBitmap(), xsrcMask, ysrcMask, MAKEROP4(dwRop, DSTCOPY) - ) != 0; + ) != 0; + } } if ( !success ) @@ -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")); }