X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/95c1ea29edb833d5d0ab820f01770ddcc0181ed0..bdebb379299aaf1ee588dbe15968829df49ccedc:/src/msw/dc.cpp diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 4529ec2d4a..86e464506c 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -29,6 +29,7 @@ #endif #ifndef WX_PRECOMP + #include "wx/image.h" #include "wx/window.h" #include "wx/dc.h" #include "wx/utils.h" @@ -40,9 +41,6 @@ #include "wx/icon.h" #endif -#include "wx/msw/private.h" // needs to be before #include -#include "wx/msw/missing.h" // needs to be before #include - #include "wx/sysopt.h" #include "wx/dcprint.h" #include "wx/module.h" @@ -53,12 +51,8 @@ #endif #include -#include - -#if wxUSE_COMMON_DIALOGS && !defined(__WXMICROWIN__) - #include -#endif +#include "wx/msw/wrapcdlg.h" #ifndef __WIN32__ #include #endif @@ -93,11 +87,6 @@ static const int VIEWPORT_EXTENT = 1000; static const int MM_POINTS = 9; static const int MM_METRIC = 10; -// usually this is defined in math.h -#ifndef M_PI - static const double M_PI = 3.14159265358979323846; -#endif // M_PI - // ROPs which don't have standard names (see "Ternary Raster Operations" in the // MSDN docs for how this and other numbers in wxDC::Blit() are obtained) #define DSTCOPY 0x00AA0029 // a.k.a. NOP operation @@ -113,13 +102,17 @@ static const int MM_METRIC = 10; coordinates used. */ -// logical to device -#define XLOG2DEV(x) (x) -#define YLOG2DEV(y) (y) - -// device to logical -#define XDEV2LOG(x) (x) -#define YDEV2LOG(y) (y) +#ifdef __WXWINCE__ + #define XLOG2DEV(x) ((x-m_logicalOriginX)*m_signX) + #define YLOG2DEV(y) ((y-m_logicalOriginY)*m_signY) + #define XDEV2LOG(x) ((x)*m_signX+m_logicalOriginX) + #define YDEV2LOG(y) ((y)*m_signY+m_logicalOriginY) +#else + #define XLOG2DEV(x) (x) + #define YLOG2DEV(y) (y) + #define XDEV2LOG(x) (x) + #define YDEV2LOG(y) (y) +#endif // --------------------------------------------------------------------------- // private functions @@ -138,13 +131,13 @@ static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } // otherwise static bool AlphaBlt(HDC hdcDst, int x, int y, int w, int h, - HDC hdcSrc, + int srcX, int srcY, HDC hdcSrc, const wxBitmap& bmpSrc); #ifdef wxHAVE_RAW_BITMAP // our (limited) AlphaBlend() replacement static void -wxAlphaBlend(HDC hdcDst, int x, int y, int w, int h, const wxBitmap& bmp); +wxAlphaBlend(HDC hdcDst, int x, int y, int w, int h, int srcX, int srcY, const wxBitmap& bmp); #endif // ---------------------------------------------------------------------------- @@ -184,6 +177,8 @@ public: m_modeOld = ::SetStretchBltMode(m_hdc, mode); if ( !m_modeOld ) wxLogLastError(_T("SetStretchBltMode")); +#else + wxUnusedVar(mode); #endif } @@ -220,7 +215,7 @@ wxColourChanger::wxColourChanger(wxDC& dc) : m_dc(dc) m_colFgOld = ::GetTextColor(hdc); m_colBgOld = ::GetBkColor(hdc); - // note that Windows convention is opposite to wxWindows one, this is + // note that Windows convention is opposite to wxWidgets one, this is // why text colour becomes the background one and vice versa const wxColour& colFg = dc.GetTextForeground(); if ( colFg.Ok() ) @@ -379,6 +374,24 @@ void wxDC::UpdateClipBox() m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom); } +void +wxDC::DoGetClippingBox(wxCoord *x, wxCoord *y, wxCoord *w, wxCoord *h) const +{ + // check if we should try to retrieve the clipping region possibly not set + // by our SetClippingRegion() but preset by Windows:this can only happen + // when we're associated with an existing HDC usign SetHDC(), see there + if ( m_clipping && !m_clipX1 && !m_clipX2 ) + { + wxDC *self = wxConstCast(this, wxDC); + self->UpdateClipBox(); + + if ( !m_clipX1 && !m_clipX2 ) + self->m_clipping = false; + } + + wxDCBase::DoGetClippingBox(x, y, w, h); +} + // common part of DoSetClippingRegion() and DoSetClippingRegionAsRegion() void wxDC::SetClippingHrgn(WXHRGN hrgn) { @@ -389,11 +402,17 @@ void wxDC::SetClippingHrgn(WXHRGN hrgn) // note that we combine the new clipping region with the existing one: this // is compatible with what the other ports do and is the documented // behaviour now (starting with 2.3.3) -#if defined(__WIN16__) || defined(__WXWINCE__) +#if defined(__WXWINCE__) RECT rectClip; if ( !::GetClipBox(GetHdc(), &rectClip) ) return; + // GetClipBox returns logical coordinates, so transform to device + rectClip.left = LogicalToDeviceX(rectClip.left); + rectClip.top = LogicalToDeviceY(rectClip.top); + rectClip.right = LogicalToDeviceX(rectClip.right); + rectClip.bottom = LogicalToDeviceY(rectClip.bottom); + HRGN hrgnDest = ::CreateRectRgn(0, 0, 0, 0); HRGN hrgnClipOld = ::CreateRectRgn(rectClip.left, rectClip.top, rectClip.right, rectClip.bottom); @@ -405,14 +424,14 @@ void wxDC::SetClippingHrgn(WXHRGN hrgn) ::DeleteObject(hrgnClipOld); ::DeleteObject(hrgnDest); -#else // Win32 +#else // !WinCE if ( ::ExtSelectClipRgn(GetHdc(), (HRGN)hrgn, RGN_AND) == ERROR ) { wxLogLastError(_T("ExtSelectClipRgn")); return; } -#endif // Win16/32 +#endif // WinCE/!WinCE m_clipping = true; @@ -461,7 +480,7 @@ void wxDC::DestroyClippingRegion() ::DeleteObject(rgn); } - m_clipping = false; + wxDCBase::DestroyClippingRegion(); } // --------------------------------------------------------------------------- @@ -528,10 +547,10 @@ void wxDC::Clear() ::FillRect(GetHdc(), &rect, brush); ::DeleteObject(brush); +#ifndef __WXWINCE__ int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX, height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY; -#ifndef __WXWINCE__ ::SetMapMode(GetHdc(), MM_ANISOTROPIC); ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL); @@ -544,6 +563,10 @@ void wxDC::Clear() bool wxDC::DoFloodFill(wxCoord x, wxCoord y, const wxColour& col, int style) { #ifdef __WXWINCE__ + wxUnusedVar(x); + wxUnusedVar(y); + wxUnusedVar(col); + wxUnusedVar(style); return false; #else @@ -699,8 +722,8 @@ void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, #else DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK); #endif -#else // Win16 - // In WIN16, draw a cross +#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); @@ -714,7 +737,7 @@ void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, ::SelectObject(GetHdc(), hPenOld); ::SelectObject(GetHdc(), hBrushOld); ::DeleteObject(blackPen); -#endif // Win32/16 +#endif // Win32/Symantec-MicroWin CalcBoundingBox(x1, y1); CalcBoundingBox(x2, y2); @@ -755,6 +778,8 @@ void wxDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffs } #ifndef __WXWINCE__ int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING); +#else + wxUnusedVar(fillStyle); #endif (void)Polygon(GetHdc(), cpoints, n); #ifndef __WXWINCE__ @@ -788,7 +813,7 @@ wxDC::DoDrawPolyPolygon(int n, { #ifdef __WXWINCE__ wxDCBase::DoDrawPolyPolygon(n, count, points, xoffset, yoffset, fillStyle); -#else +#else WXMICROWIN_CHECK_HDC wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling @@ -809,11 +834,11 @@ wxDC::DoDrawPolyPolygon(int n, } #ifndef __WXWINCE__ int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING); -#endif +#endif (void)PolyPolygon(GetHdc(), cpoints, count, n); #ifndef __WXWINCE__ SetPolyFillMode(GetHdc(),prev); -#endif +#endif delete[] cpoints; } else @@ -823,11 +848,11 @@ wxDC::DoDrawPolyPolygon(int n, #ifndef __WXWINCE__ int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING); -#endif +#endif (void)PolyPolygon(GetHdc(), (POINT*) points, count, n); #ifndef __WXWINCE__ SetPolyFillMode(GetHdc(),prev); -#endif +#endif } #endif // __WXWINCE__ @@ -889,8 +914,11 @@ void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) // I wonder if this shouldn´t be done after the LOG2DEV() conversions. RR. if ( m_pen.GetStyle() == wxTRANSPARENT ) { + // Apparently not needed for WinCE (see e.g. Life! demo) +#ifndef __WXWINCE__ x2++; y2++; +#endif } (void)Rectangle(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2)); @@ -1037,7 +1065,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, hdcMem, bmp) ) + if ( AlphaBlt(GetHdc(), x, y, width, height, 0, 0, hdcMem, bmp) ) return; } @@ -1060,7 +1088,7 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask // use MaskBlt() with ROP which doesn't do anything to dst in the mask // points // On some systems, MaskBlt succeeds yet is much much slower - // than the wxWindows fall-back implementation. So we need + // than the wxWidgets fall-back implementation. So we need // to be able to switch this on and off at runtime. bool ok = false; #if wxUSE_SYSTEM_OPTIONS @@ -1262,13 +1290,13 @@ void wxDC::DoDrawRotatedText(const wxString& text, // "upper left" and "upper right" CalcBoundingBox(x, y); - CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(h*sin(rad))); + CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(w*sin(rad))); // "bottom left" and "bottom right" x += (wxCoord)(h*sin(rad)); y += (wxCoord)(h*cos(rad)); CalcBoundingBox(x, y); - CalcBoundingBox(x + wxCoord(h*sin(rad)), y + wxCoord(h*cos(rad))); + CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(w*sin(rad))); } #endif } @@ -1743,15 +1771,13 @@ void wxDC::SetUserScale(double x, double y) { WXMICROWIN_CHECK_HDC -#ifndef __WXWINCE__ if ( x == m_userScaleX && y == m_userScaleY ) return; m_userScaleX = x; m_userScaleY = y; - SetMapMode(m_mappingMode); -#endif + this->SetMapMode(m_mappingMode); } void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp) @@ -1769,6 +1795,9 @@ void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp) SetMapMode(m_mappingMode); } +#else + wxUnusedVar(xLeftRight); + wxUnusedVar(yBottomUp); #endif } @@ -1776,13 +1805,13 @@ void wxDC::SetSystemScale(double x, double y) { WXMICROWIN_CHECK_HDC -#ifndef __WXWINCE__ if ( x == m_scaleX && y == m_scaleY ) return; m_scaleX = x; m_scaleY = y; +#ifndef __WXWINCE__ SetMapMode(m_mappingMode); #endif } @@ -1791,13 +1820,13 @@ void wxDC::SetLogicalOrigin(wxCoord x, wxCoord y) { WXMICROWIN_CHECK_HDC -#ifndef __WXWINCE__ if ( x == m_logicalOriginX && y == m_logicalOriginY ) return; m_logicalOriginX = x; m_logicalOriginY = y; +#ifndef __WXWINCE__ ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL); #endif } @@ -1806,7 +1835,6 @@ void wxDC::SetDeviceOrigin(wxCoord x, wxCoord y) { WXMICROWIN_CHECK_HDC -#ifndef __WXWINCE__ if ( x == m_deviceOriginX && y == m_deviceOriginY ) return; @@ -1814,7 +1842,6 @@ void wxDC::SetDeviceOrigin(wxCoord x, wxCoord y) m_deviceOriginY = y; ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL); -#endif } // --------------------------------------------------------------------------- @@ -1879,11 +1906,14 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, WXMICROWIN_CHECK_HDC_RET(false) + // if either the source or destination has alpha channel, we must use + // AlphaBlt() as other function don't handle it correctly const wxBitmap& bmpSrc = source->m_selectedBitmap; - if ( bmpSrc.Ok() && bmpSrc.HasAlpha() ) + if ( bmpSrc.Ok() && (bmpSrc.HasAlpha() || + (m_selectedBitmap.Ok() && m_selectedBitmap.HasAlpha())) ) { if ( AlphaBlt(GetHdc(), xdest, ydest, width, height, - GetHdcOf(*source), bmpSrc) ) + xsrc, ysrc, GetHdcOf(*source), bmpSrc) ) return true; } @@ -1951,7 +1981,7 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, // of the mask which is also contrary to the Windows one) // On some systems, MaskBlt succeeds yet is much much slower - // than the wxWindows fall-back implementation. So we need + // than the wxWidgets fall-back implementation. So we need // to be able to switch this on and off at runtime. #if wxUSE_SYSTEM_OPTIONS if (wxSystemOptions::GetOptionInt(wxT("no-maskblt")) == 0) @@ -2093,7 +2123,11 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, SRCCOPY ) == (int)GDI_ERROR ) { - wxLogLastError(wxT("StretchDIBits")); + // On Win9x this API fails most (all?) of the time, so + // logging it becomes quite distracting. Since it falls + // back to the code below this is not really serious, so + // don't log it. + //wxLogLastError(wxT("StretchDIBits")); } else { @@ -2194,7 +2228,7 @@ void wxDC::DoGetSizeMM(int *w, int *h) const wxSize wxDC::GetPPI() const { - WXMICROWIN_CHECK_HDC_RET(wxSize()) + WXMICROWIN_CHECK_HDC_RET(wxSize(0,0)) int x = ::GetDeviceCaps(GetHdc(), LOGPIXELSX); int y = ::GetDeviceCaps(GetHdc(), LOGPIXELSY); @@ -2202,7 +2236,7 @@ wxSize wxDC::GetPPI() const return wxSize(x, y); } -// For use by wxWindows only, unless custom units are required. +// For use by wxWidgets only, unless custom units are required. void wxDC::SetLogicalScale(double x, double y) { WXMICROWIN_CHECK_HDC @@ -2354,7 +2388,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) static bool AlphaBlt(HDC hdcDst, int x, int y, int width, int height, - HDC hdcSrc, + int srcX, int srcY, HDC hdcSrc, const wxBitmap& bmp) { wxASSERT_MSG( bmp.Ok() && bmp.HasAlpha(), _T("AlphaBlt(): invalid bitmap") ); @@ -2402,7 +2436,7 @@ static bool AlphaBlt(HDC hdcDst, bf.AlphaFormat = AC_SRC_ALPHA; if ( pfnAlphaBlend(hdcDst, x, y, width, height, - hdcSrc, 0, 0, width, height, + hdcSrc, srcX, srcY, width, height, bf) ) { // skip wxAlphaBlend() call below @@ -2416,12 +2450,13 @@ 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, bmp); + wxAlphaBlend(hdcDst, x, y, width, height, srcX, srcY, bmp); return true; #else // !wxHAVE_RAW_BITMAP // no wxAlphaBlend() neither, fall back to using simple BitBlt() (we lose // alpha but at least something will be shown like this) + wxUnusedVar(bmp); return false; #endif // wxHAVE_RAW_BITMAP } @@ -2431,7 +2466,7 @@ static bool AlphaBlt(HDC hdcDst, #ifdef wxHAVE_RAW_BITMAP static void -wxAlphaBlend(HDC hdcDst, int xDst, int yDst, int w, int h, const wxBitmap& bmpSrc) +wxAlphaBlend(HDC hdcDst, int xDst, int yDst, int w, int h, int srcX, int srcY, const wxBitmap& bmpSrc) { // get the destination DC pixels wxBitmap bmpDst(w, h, 32 /* force creating RGBA DIB */); @@ -2453,11 +2488,13 @@ wxAlphaBlend(HDC hdcDst, int xDst, int yDst, int w, int h, const wxBitmap& bmpSr wxAlphaPixelData::Iterator pDst(dataDst), pSrc(dataSrc); + pSrc.Offset(dataSrc, srcX, srcY); + for ( int y = 0; y < h; y++ ) { wxAlphaPixelData::Iterator pDstRowStart = pDst, pSrcRowStart = pSrc; - + for ( int x = 0; x < w; x++ ) { // note that source bitmap uses premultiplied alpha (as required by