X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/481203cb23ab64f570b2046f7154a94e0561f3e7..180b5b4827d08f1ac13bbb5eca03f775ab35a0b1:/src/msw/dc.cpp diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 1bd9b7195c..fa9c434fb4 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -25,6 +25,7 @@ #endif #ifndef WX_PRECOMP + #include "wx/msw/wrapcdlg.h" #include "wx/image.h" #include "wx/window.h" #include "wx/dc.h" @@ -35,11 +36,11 @@ #include "wx/dcmemory.h" #include "wx/log.h" #include "wx/icon.h" + #include "wx/dcprint.h" + #include "wx/module.h" #endif #include "wx/sysopt.h" -#include "wx/dcprint.h" -#include "wx/module.h" #include "wx/dynlib.h" #ifdef wxHAVE_RAW_BITMAP @@ -48,13 +49,16 @@ #include -#include "wx/msw/wrapcdlg.h" #ifndef __WIN32__ #include #endif #ifndef AC_SRC_ALPHA -#define AC_SRC_ALPHA 1 + #define AC_SRC_ALPHA 1 +#endif + +#ifndef LAYOUT_RTL + #define LAYOUT_RTL 1 #endif /* Quaternary raster codes */ @@ -126,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 @@ -196,36 +205,48 @@ private: DECLARE_NO_COPY_CLASS(StretchBltModeChanger) }; -// support for dynamic loading of msimg32.dll which we use for some functions -class wxMSImg32DLL +#if wxUSE_DYNLIB_CLASS + +// helper class to cache dynamically loaded libraries and not attempt reloading +// them if it fails +class wxOnceOnlyDLLLoader { public: - // return the symbol with the given name if the DLL not loaded or symbol - // not present - static void *GetSymbol(const wxChar *name) + // ctor argument must be a literal string as we don't make a copy of it! + wxOnceOnlyDLLLoader(const wxChar *dllName) + : m_dllName(dllName) { + } + + + // return the symbol with the given name or NULL if the DLL not loaded + // or symbol not present + void *GetSymbol(const wxChar *name) + { + // we're prepared to handle errors here wxLogNull noLog; - if ( !ms_triedToLoad ) + if ( m_dllName ) { - ms_triedToLoad = true; - ms_dll.Load(_T("msimg32")); + m_dll.Load(m_dllName); + + // reset the name whether we succeeded or failed so that we don't + // try again the next time + m_dllName = NULL; } - return ms_dll.IsLoaded() ? ms_dll.GetSymbol(name) : NULL; + return m_dll.IsLoaded() ? m_dll.GetSymbol(name) : NULL; } private: - static wxDynamicLibrary ms_dll; - static bool ms_triedToLoad; + wxDynamicLibrary m_dll; + const wxChar *m_dllName; }; -wxDynamicLibrary wxMSImg32DLL::ms_dll; -bool wxMSImg32DLL::ms_triedToLoad = false; +static wxOnceOnlyDLLLoader wxGDI32DLL(_T("gdi32")); +static wxOnceOnlyDLLLoader wxMSIMG32DLL(_T("msimg32")); -// helper macro for getting the symbols from msimg32.dll: it supposes that a -// type "name_t" is defined and casts the returned symbol to it automatically -#define wxMSIMG32_SYMBOL(name) (name ## _t)wxMSImg32DLL::GetSymbol(_T(#name)) +#endif // wxUSE_DYNLIB_CLASS // =========================================================================== // implementation @@ -490,7 +511,7 @@ void wxDC::DestroyClippingRegion() // on desktop WIN32 also, since the WIN32 docs imply that the user // clipping region is independent from the paint clipping region. ::SelectClipRgn(GetHdc(), 0); -#else +#else // TODO: this should restore the previous clipping region, // so that OnPaint processing works correctly, and the update // clipping region doesn't get destroyed after the first @@ -498,7 +519,7 @@ void wxDC::DestroyClippingRegion() HRGN rgn = CreateRectRgn(0, 0, 32000, 32000); ::SelectClipRgn(GetHdc(), rgn); ::DeleteObject(rgn); -#endif +#endif } wxDCBase::DestroyClippingRegion(); @@ -554,9 +575,9 @@ void wxDC::Clear() if (!m_selectedBitmap.Ok()) return; - rect.left = 0; rect.top = 0; - rect.right = m_selectedBitmap.GetWidth(); - rect.bottom = m_selectedBitmap.GetHeight(); + rect.left = -m_deviceOriginX; rect.top = -m_deviceOriginY; + rect.right = m_selectedBitmap.GetWidth()-m_deviceOriginX; + rect.bottom = m_selectedBitmap.GetHeight()-m_deviceOriginY; } #ifndef __WXWINCE__ @@ -568,17 +589,7 @@ void wxDC::Clear() ::FillRect(GetHdc(), &rect, brush); ::DeleteObject(brush); -#ifndef __WXWINCE__ - int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX, - height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY; - - ::SetMapMode(GetHdc(), MM_ANISOTROPIC); - - ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL); - ::SetWindowExtEx(GetHdc(), width, height, NULL); - ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL); - ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL); -#endif + RealizeScaleAndOrigin(); } bool wxDC::DoFloodFill(wxCoord WXUNUSED_IN_WINCE(x), @@ -724,12 +735,13 @@ void wxDC::DoDrawArc(wxCoord x1, wxCoord y1, void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height) { - WXMICROWIN_CHECK_HDC - + // cases when we don't have DrawFrameControl() +#if defined(__SYMANTEC__) || defined(__WXMICROWIN__) + return wxDCBase::DoDrawCheckMark(x1, y1, width, height); +#else // normal case wxCoord x2 = x1 + width, y2 = y1 + height; -#if defined(__WIN32__) && !defined(__SYMANTEC__) && !defined(__WXMICROWIN__) RECT rect; rect.left = x1; rect.top = y1; @@ -741,25 +753,10 @@ void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, #else DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK); #endif -#else // Symantec-MicroWin - // draw a cross - HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); - HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH); - HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen); - HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush); - ::SetROP2(GetHdc(), R2_COPYPEN); - Rectangle(GetHdc(), x1, y1, x2, y2); - MoveToEx(GetHdc(), x1, y1, NULL); - LineTo(GetHdc(), x2, y2); - MoveToEx(GetHdc(), x2, y1, NULL); - LineTo(GetHdc(), x1, y2); - ::SelectObject(GetHdc(), hPenOld); - ::SelectObject(GetHdc(), hBrushOld); - ::DeleteObject(blackPen); -#endif // Win32/Symantec-MicroWin CalcBoundingBox(x1, y1); CalcBoundingBox(x2, y2); +#endif // Microwin/Normal } void wxDC::DoDrawPoint(wxCoord x, wxCoord y) @@ -932,7 +929,7 @@ void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) // transparent pen) one pixel smaller in both directions and we want them // to have the same size regardless of which pen is used - adjust - // I wonder if this shouldn´t be done after the LOG2DEV() conversions. RR. + // I wonder if this shouldnt be done after the LOG2DEV() conversions. RR. if ( m_pen.GetStyle() == wxTRANSPARENT ) { // Apparently not needed for WinCE (see e.g. Life! demo) @@ -1000,7 +997,7 @@ void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) } #if wxUSE_SPLINES -void wxDC::DoDrawSpline(wxList *points) +void wxDC::DoDrawSpline(const wxPointList *points) { #ifdef __WXWINCE__ // WinCE does not support ::PolyBezier so use generic version @@ -1032,8 +1029,8 @@ void wxDC::DoDrawSpline(wxList *points) size_t bezier_pos = 0; wxCoord x1, y1, x2, y2, cx1, cy1, cx4, cy4; - wxList::compatibility_iterator node = points->GetFirst(); - wxPoint *p = (wxPoint *)node->GetData(); + wxPointList::compatibility_iterator node = points->GetFirst(); + wxPoint *p = node->GetData(); lppt[ bezier_pos ].x = x1 = p->x; lppt[ bezier_pos ].y = y1 = p->y; bezier_pos++; @@ -1041,7 +1038,7 @@ void wxDC::DoDrawSpline(wxList *points) bezier_pos++; node = node->GetNext(); - p = (wxPoint *)node->GetData(); + p = node->GetData(); x2 = p->x; y2 = p->y; @@ -1125,6 +1122,17 @@ void wxDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,d rx2 += (int)(100.0 * abs(w) * cos(ea)); ry2 -= (int)(100.0 * abs(h) * m_signY * sin(ea)); + // Swap start and end positions if the end angle is less than the start angle. + if (ea < sa) { + int temp; + temp = rx2; + rx2 = rx1; + rx1 = temp; + temp = ry2; + ry2 = ry1; + ry1 = temp; + } + // draw pie with NULL_PEN first and then outline otherwise a line is // drawn from the start and end points to the centre HPEN hpenOld = (HPEN) ::SelectObject(GetHdc(), (HPEN) ::GetStockObject(NULL_PEN)); @@ -1185,7 +1193,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; } @@ -1247,7 +1255,8 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask // Rather than reproduce wxDC::Blit, let's do it at the wxWin API // level wxMemoryDC memDC; - memDC.SelectObject(bmp); + + memDC.SelectObjectAsSource(bmp); Blit(x, y, width, height, &memDC, 0, 0, wxCOPY, useMask); @@ -1502,7 +1511,7 @@ void wxDC::SetFont(const wxFont& font) else // selected ok { if ( !m_oldFont ) - m_oldFont = (WXHPEN)hfont; + m_oldFont = (WXHFONT)hfont; m_font = font; } @@ -1595,7 +1604,7 @@ void wxDC::SetBrush(const wxBrush& brush) else // selected ok { if ( !m_oldBrush ) - m_oldBrush = (WXHPEN)hbrush; + m_oldBrush = (WXHBRUSH)hbrush; m_brush = brush; } @@ -1727,7 +1736,7 @@ wxCoord wxDC::GetCharWidth() const void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, wxCoord *descent, wxCoord *externalLeading, - wxFont *font) const + const wxFont *font) const { #ifdef __WXMICROWIN__ if (!GetHDC()) @@ -1754,14 +1763,16 @@ void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, SIZE sizeRect; const size_t len = string.length(); - if ( !::GetTextExtentPoint32(GetHdc(), string, len, &sizeRect) ) + if ( !::GetTextExtentPoint32(GetHdc(), string.wx_str(), len, &sizeRect) ) { wxLogLastError(_T("GetTextExtentPoint32()")); } +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) // the result computed by GetTextExtentPoint32() may be too small as it // accounts for under/overhang of the first/last character while we want // just the bounding rect for this string so adjust the width as needed + // (using API not available in 2002 SDKs of WinCE) if ( len > 0 ) { ABC width; @@ -1783,6 +1794,7 @@ void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, } //else: GetCharABCWidths() failed, not a TrueType font? } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) TEXTMETRIC tm; ::GetTextMetrics(GetHdc(), &tm); @@ -1818,8 +1830,8 @@ bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) con { // Win9x and WinNT+ have different limits int version = wxGetOsVersion(); - maxLenText = version == wxWINDOWS_NT ? 65535 : 8192; - maxWidth = version == wxWINDOWS_NT ? INT_MAX : 32767; + maxLenText = version == wxOS_WINDOWS_NT ? 65535 : 8192; + maxWidth = version == wxOS_WINDOWS_NT ? INT_MAX : 32767; } widths.Empty(); @@ -1844,8 +1856,25 @@ bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) con return true; } +void wxDC::RealizeScaleAndOrigin() +{ + // VZ: it seems very wasteful to always use MM_ANISOTROPIC when in 99% of + // cases we could do with MM_TEXT and in the remaining 0.9% with + // MM_ISOTROPIC (TODO!) +#ifndef __WXWINCE__ + ::SetMapMode(GetHdc(), MM_ANISOTROPIC); + int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX, + height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY; + ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL); + ::SetWindowExtEx(GetHdc(), width, height, NULL); + + ::SetViewportOrgEx(GetHdc(), m_deviceOriginX, m_deviceOriginY, NULL); + ::SetWindowOrgEx(GetHdc(), m_logicalOriginX, m_logicalOriginY, NULL); +#endif + +} void wxDC::SetMapMode(int mode) { @@ -1900,22 +1929,10 @@ void wxDC::SetMapMode(int mode) wxFAIL_MSG( _T("unknown mapping mode in SetMapMode") ); } } - - // VZ: it seems very wasteful to always use MM_ANISOTROPIC when in 99% of - // cases we could do with MM_TEXT and in the remaining 0.9% with - // MM_ISOTROPIC (TODO!) -#ifndef __WXWINCE__ - ::SetMapMode(GetHdc(), MM_ANISOTROPIC); - - int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX, - height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY; - - ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL); - ::SetWindowExtEx(GetHdc(), width, height, NULL); - - ::SetViewportOrgEx(GetHdc(), m_deviceOriginX, m_deviceOriginY, NULL); - ::SetWindowOrgEx(GetHdc(), m_logicalOriginX, m_logicalOriginY, NULL); -#endif + + ComputeScaleAndOrigin(); + + RealizeScaleAndOrigin(); } void wxDC::SetUserScale(double x, double y) @@ -1925,44 +1942,25 @@ void wxDC::SetUserScale(double x, double y) if ( x == m_userScaleX && y == m_userScaleY ) return; - m_userScaleX = x; - m_userScaleY = y; - - this->SetMapMode(m_mappingMode); + wxDCBase::SetUserScale(x,y); + + RealizeScaleAndOrigin(); } -void wxDC::SetAxisOrientation(bool WXUNUSED_IN_WINCE(xLeftRight), - bool WXUNUSED_IN_WINCE(yBottomUp)) +void wxDC::SetAxisOrientation(bool xLeftRight, + bool yBottomUp) { WXMICROWIN_CHECK_HDC -#ifndef __WXWINCE__ int signX = xLeftRight ? 1 : -1, signY = yBottomUp ? -1 : 1; - - if ( signX != m_signX || signY != m_signY ) - { - m_signX = signX; - m_signY = signY; - - SetMapMode(m_mappingMode); - } -#endif -} - -void wxDC::SetSystemScale(double x, double y) -{ - WXMICROWIN_CHECK_HDC - - if ( x == m_scaleX && y == m_scaleY ) + + if (signX == m_signX && signY == m_signY) return; + + wxDCBase::SetAxisOrientation( xLeftRight, yBottomUp ); - m_scaleX = x; - m_scaleY = y; - -#ifndef __WXWINCE__ - SetMapMode(m_mappingMode); -#endif + RealizeScaleAndOrigin(); } void wxDC::SetLogicalOrigin(wxCoord x, wxCoord y) @@ -1972,8 +1970,7 @@ void wxDC::SetLogicalOrigin(wxCoord x, wxCoord y) if ( x == m_logicalOriginX && y == m_logicalOriginY ) return; - m_logicalOriginX = x; - m_logicalOriginY = y; + wxDCBase::SetLogicalOrigin( x, y ); #ifndef __WXWINCE__ ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL); @@ -1986,70 +1983,33 @@ void wxDC::SetDeviceOrigin(wxCoord x, wxCoord y) if ( x == m_deviceOriginX && y == m_deviceOriginY ) return; - - m_deviceOriginX = x; - m_deviceOriginY = y; + + wxDCBase::SetDeviceOrigin( x, y ); ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL); } // --------------------------------------------------------------------------- -// coordinates transformations +// bit blit // --------------------------------------------------------------------------- -wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const -{ - return DeviceToLogicalXRel(x - m_deviceOriginX)*m_signX + m_logicalOriginX; -} - -wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const -{ - // axis orientation is not taken into account for conversion of a distance - return (wxCoord)(x / (m_logicalScaleX*m_userScaleX*m_scaleX)); -} - -wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const -{ - return DeviceToLogicalYRel(y - m_deviceOriginY)*m_signY + m_logicalOriginY; -} - -wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const -{ - // axis orientation is not taken into account for conversion of a distance - return (wxCoord)( y / (m_logicalScaleY*m_userScaleY*m_scaleY)); -} - -wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const -{ - return LogicalToDeviceXRel(x - m_logicalOriginX)*m_signX + m_deviceOriginX; -} - -wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const -{ - // axis orientation is not taken into account for conversion of a distance - return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_scaleX); -} - -wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const +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 LogicalToDeviceYRel(y - m_logicalOriginY)*m_signY + m_deviceOriginY; + return DoStretchBlit(dstX, dstY, dstWidth, dstHeight, source, srcX, srcY, dstWidth, dstHeight, rop, useMask, srcMaskX, srcMaskY); } -wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const -{ - // axis orientation is not taken into account for conversion of a distance - return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_scaleY); -} - -// --------------------------------------------------------------------------- -// bit blit -// --------------------------------------------------------------------------- - -bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, - wxCoord width, wxCoord height, - wxDC *source, wxCoord xsrc, wxCoord ysrc, - int rop, bool useMask, - wxCoord xsrcMask, wxCoord ysrcMask) +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") ); @@ -2061,8 +2021,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; } @@ -2136,16 +2096,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 ) @@ -2165,55 +2128,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 ) { @@ -2258,18 +2225,18 @@ 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, - SRCCOPY + dwRop ) == (int)GDI_ERROR ) { // On Win9x this API fails most (all?) of the time, so @@ -2296,9 +2263,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 ) ) { @@ -2316,7 +2283,7 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, ( GetHdc(), xdest, ydest, - (int)width, (int)height, + (int)dstWidth, (int)dstHeight, GetHdcOf(*source), xsrc, ysrc, dwRop @@ -2392,8 +2359,7 @@ void wxDC::SetLogicalScale(double x, double y) { WXMICROWIN_CHECK_HDC - m_logicalScaleX = x; - m_logicalScaleY = y; + wxDCBase::SetLogicalScale(x,y); } // ---------------------------------------------------------------------------- @@ -2538,8 +2504,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") ); @@ -2552,7 +2520,8 @@ static bool AlphaBlt(HDC hdcDst, HDC,int,int,int,int, BLENDFUNCTION); - static AlphaBlend_t pfnAlphaBlend = wxMSIMG32_SYMBOL(AlphaBlend); + static AlphaBlend_t + pfnAlphaBlend = (AlphaBlend_t)wxMSIMG32DLL.GetSymbol(_T("AlphaBlend")); if ( pfnAlphaBlend ) { BLENDFUNCTION bf; @@ -2561,8 +2530,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 @@ -2578,7 +2547,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 @@ -2595,15 +2564,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")); } @@ -2618,15 +2589,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(); @@ -2636,17 +2609,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")); } @@ -2665,7 +2635,8 @@ void wxDC::DoGradientFillLinear (const wxRect& rect, #if defined(GRADIENT_FILL_RECT_H) && wxUSE_DYNLIB_CLASS typedef BOOL (WINAPI *GradientFill_t)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG); - static GradientFill_t pfnGradientFill = wxMSIMG32_SYMBOL(GradientFill); + static GradientFill_t pfnGradientFill = + (GradientFill_t)wxMSIMG32DLL.GetSymbol(_T("GradientFill")); if ( pfnGradientFill ) { @@ -2682,8 +2653,8 @@ void wxDC::DoGradientFillLinear (const wxRect& rect, vertices[0].x = rect.GetLeft(); vertices[0].y = rect.GetTop(); - vertices[1].x = rect.GetRight(); - vertices[1].y = rect.GetBottom(); + vertices[1].x = rect.GetRight()+1; + vertices[1].y = rect.GetBottom()+1; vertices[firstVertex].Red = (COLOR16)(initialColour.Red() << 8); vertices[firstVertex].Green = (COLOR16)(initialColour.Green() << 8); @@ -2716,3 +2687,62 @@ void wxDC::DoGradientFillLinear (const wxRect& rect, wxDCBase::DoGradientFillLinear(rect, initialColour, destColour, nDirection); } + +#if wxUSE_DYNLIB_CLASS + +static DWORD wxGetDCLayout(HDC hdc) +{ + typedef DWORD (WINAPI *GetLayout_t)(HDC); + static GetLayout_t + pfnGetLayout = (GetLayout_t)wxGDI32DLL.GetSymbol(_T("GetLayout")); + + return pfnGetLayout ? pfnGetLayout(hdc) : (DWORD)-1; +} + +wxLayoutDirection wxDC::GetLayoutDirection() const +{ + DWORD layout = wxGetDCLayout(GetHdc()); + + if ( layout == (DWORD)-1 ) + return wxLayout_Default; + + return layout & LAYOUT_RTL ? wxLayout_RightToLeft : wxLayout_LeftToRight; +} + +void wxDC::SetLayoutDirection(wxLayoutDirection dir) +{ + typedef DWORD (WINAPI *SetLayout_t)(HDC, DWORD); + static SetLayout_t + pfnSetLayout = (SetLayout_t)wxGDI32DLL.GetSymbol(_T("SetLayout")); + if ( !pfnSetLayout ) + return; + + if ( dir == wxLayout_Default ) + { + dir = wxTheApp->GetLayoutDirection(); + if ( dir == wxLayout_Default ) + return; + } + + DWORD layout = wxGetDCLayout(GetHdc()); + if ( dir == wxLayout_RightToLeft ) + layout |= LAYOUT_RTL; + else + layout &= ~LAYOUT_RTL; + + pfnSetLayout(GetHdc(), layout); +} + +#else // !wxUSE_DYNLIB_CLASS + +// we can't provide RTL support without dynamic loading, so stub it out +wxLayoutDirection wxDC::GetLayoutDirection() const +{ + return wxLayout_Default; +} + +void wxDC::SetLayoutDirection(wxLayoutDirection WXUNUSED(dir)) +{ +} + +#endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS