X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/beb966c53d7a9e63b2aa6c4e6cd7156e269f8a1e..730d336601a3ece761b56e7c05d1099352670a25:/src/msw/dc.cpp diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index b83bf5ba55..22e2455e0a 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,8 +41,6 @@ #include "wx/icon.h" #endif -#include "wx/msw/private.h" // needs to be before #include - #include "wx/sysopt.h" #include "wx/dcprint.h" #include "wx/module.h" @@ -52,12 +51,8 @@ #endif #include -#include - -#if wxUSE_COMMON_DIALOGS && !defined(__WXMICROWIN__) - #include -#endif +#include "wx/msw/wrapcdlg.h" #ifndef __WIN32__ #include #endif @@ -92,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 @@ -112,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+m_deviceOriginX) + #define YLOG2DEV(y) ((y-m_logicalOriginY)*m_signY+m_deviceOriginY) + #define XDEV2LOG(x) ((x-m_deviceOriginX)*m_signX+m_logicalOriginX) + #define YDEV2LOG(y) ((y-m_deviceOriginY)*m_signY+m_logicalOriginY) +#else + #define XLOG2DEV(x) (x) + #define YLOG2DEV(y) (y) + #define XDEV2LOG(x) (x) + #define YDEV2LOG(y) (y) +#endif // --------------------------------------------------------------------------- // private functions @@ -183,6 +177,8 @@ public: m_modeOld = ::SetStretchBltMode(m_hdc, mode); if ( !m_modeOld ) wxLogLastError(_T("SetStretchBltMode")); +#else + wxUnusedVar(mode); #endif } @@ -219,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() ) @@ -378,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) { @@ -388,7 +402,7 @@ 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; @@ -404,14 +418,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; @@ -460,7 +474,7 @@ void wxDC::DestroyClippingRegion() ::DeleteObject(rgn); } - m_clipping = false; + wxDCBase::DestroyClippingRegion(); } // --------------------------------------------------------------------------- @@ -527,10 +541,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); @@ -543,6 +557,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 @@ -698,8 +716,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); @@ -713,7 +731,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); @@ -754,6 +772,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__ @@ -779,18 +799,21 @@ void wxDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffs void wxDC::DoDrawPolyPolygon(int n, - int start[], + int count[], wxPoint points[], wxCoord xoffset, wxCoord yoffset, int fillStyle) { +#ifdef __WXWINCE__ + wxDCBase::DoDrawPolyPolygon(n, count, points, xoffset, yoffset, fillStyle); +#else WXMICROWIN_CHECK_HDC wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling int i, cnt; for (i = cnt = 0; i < n; i++) - cnt += start[i]; + cnt += count[i]; // Do things less efficiently if we have offsets if (xoffset != 0 || yoffset != 0) @@ -803,9 +826,13 @@ wxDC::DoDrawPolyPolygon(int n, CalcBoundingBox(cpoints[i].x, cpoints[i].y); } +#ifndef __WXWINCE__ int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING); - (void)PolyPolygon(GetHdc(), cpoints, start, n); +#endif + (void)PolyPolygon(GetHdc(), cpoints, count, n); +#ifndef __WXWINCE__ SetPolyFillMode(GetHdc(),prev); +#endif delete[] cpoints; } else @@ -813,10 +840,16 @@ wxDC::DoDrawPolyPolygon(int n, for (i = 0; i < cnt; i++) CalcBoundingBox(points[i].x, points[i].y); +#ifndef __WXWINCE__ int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING); - (void)PolyPolygon(GetHdc(), (POINT*) points, start, n); +#endif + (void)PolyPolygon(GetHdc(), (POINT*) points, count, n); +#ifndef __WXWINCE__ SetPolyFillMode(GetHdc(),prev); +#endif } +#endif + // __WXWINCE__ } void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset) @@ -875,8 +908,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)); @@ -1046,7 +1082,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 @@ -1248,13 +1284,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 } @@ -1611,6 +1647,49 @@ void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y, } } + +// Each element of the array will be the width of the string up to and +// including the coresoponding character in text. + +bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const +{ + static int maxLenText = -1; + static int maxWidth = -1; + int fit = 0; + SIZE sz = {0,0}; + int stlen = text.Length(); + + if (maxLenText == -1) + { + // Win9x and WinNT+ have different limits + int version = wxGetOsVersion(); + maxLenText = version == wxWINDOWS_NT ? 65535 : 8192; + maxWidth = version == wxWINDOWS_NT ? INT_MAX : 32767; + } + + widths.Empty(); + widths.Add(0, stlen); // fill the array with zeros + + if (!::GetTextExtentExPoint(GetHdc(), + text.c_str(), // string to check + wxMin(stlen, maxLenText), + maxWidth, + &fit, // [out] count of chars + // that will fit + &widths[0], // array to fill + &sz)) + { + // API failed + wxLogLastError(wxT("GetTextExtentExPoint")); + return false; + } + + return true; +} + + + + void wxDC::SetMapMode(int mode) { WXMICROWIN_CHECK_HDC @@ -1686,15 +1765,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) @@ -1712,6 +1789,9 @@ void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp) SetMapMode(m_mappingMode); } +#else + wxUnusedVar(xLeftRight); + wxUnusedVar(yBottomUp); #endif } @@ -1719,13 +1799,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 } @@ -1734,13 +1814,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 } @@ -1749,13 +1829,13 @@ void wxDC::SetDeviceOrigin(wxCoord x, wxCoord y) { WXMICROWIN_CHECK_HDC -#ifndef __WXWINCE__ if ( x == m_deviceOriginX && y == m_deviceOriginY ) return; m_deviceOriginX = x; m_deviceOriginY = y; +#ifndef __WXWINCE__ ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL); #endif } @@ -1822,8 +1902,11 @@ 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) ) @@ -1894,7 +1977,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) @@ -2036,7 +2119,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 { @@ -2137,7 +2224,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); @@ -2145,7 +2232,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 @@ -2365,6 +2452,7 @@ static bool AlphaBlt(HDC hdcDst, #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 }