X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b1c6a00e631be013b9dc3eb43959c80369a99e56..80a779275ae04443c568dca919adb26cf6f5002c:/src/common/dcbase.cpp diff --git a/src/common/dcbase.cpp b/src/common/dcbase.cpp index 9ebe1845e3..84ac42aa3c 100644 --- a/src/common/dcbase.cpp +++ b/src/common/dcbase.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: common/dcbase.cpp +// Name: src/common/dcbase.cpp // Purpose: generic methods of the wxDC Class // Author: Vadim Zeitlin // Modified by: @@ -25,14 +25,23 @@ #endif #include "wx/dc.h" -#include "wx/math.h" +#include "wx/dcbuffer.h" // for IMPLEMENT_DYNAMIC_CLASS + +#ifndef WX_PRECOMP + #include "wx/math.h" +#endif // bool wxDCBase::sm_cacheing = false; +IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject) + // ============================================================================ // implementation // ============================================================================ +IMPLEMENT_DYNAMIC_CLASS(wxBufferedDC, wxMemoryDC) +IMPLEMENT_ABSTRACT_CLASS(wxBufferedPaintDC, wxBufferedDC) + #if WXWIN_COMPATIBILITY_2_6 void wxDCBase::BeginDrawing() { @@ -412,7 +421,7 @@ bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) { int totalWidth = 0; - const size_t len = text.Length(); + const size_t len = text.length(); widths.Empty(); widths.Add(0, len); @@ -771,7 +780,7 @@ void wxDCBase::DoGradientFillLinear(const wxRect& rect, SetPen(oldPen); } -void wxDCBase::GradientFillConcentric(const wxRect& rect, +void wxDCBase::DoGradientFillConcentric(const wxRect& rect, const wxColour& initialColour, const wxColour& destColour, const wxPoint& circleCenter) @@ -817,9 +826,9 @@ void wxDCBase::GradientFillConcentric(const wxRect& rect, nGradient = 0; //get dest colors - nR = nR1 + ((nR2 - nR1) * nGradient / 100); - nG = nG1 + ((nG2 - nG1) * nGradient / 100); - nB = nB1 + ((nB2 - nB1) * nGradient / 100); + nR = (wxUint8)(nR1 + ((nR2 - nR1) * nGradient / 100)); + nG = (wxUint8)(nG1 + ((nG2 - nG1) * nGradient / 100)); + nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100)); //set the pixel m_pen.SetColour(wxColour(nR,nG,nB)); @@ -885,13 +894,13 @@ void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y, list.Append( (wxObject*) new wxPoint( x+w/2, y+h/2 ) ); // copy list into array and delete list elements - int n = list.Number(); + int n = list.GetCount(); wxPoint *points = new wxPoint[n]; int i = 0; wxNode* node = 0; - for ( node = list.First(); node; node = node->Next(), i++ ) + for ( node = list.GetFirst(); node; node = node->GetNext(), i++ ) { - wxPoint *point = (wxPoint *)node->Data(); + wxPoint *point = (wxPoint *)node->GetData(); points[i].x = point->x; points[i].y = point->y; delete point; @@ -924,9 +933,9 @@ void wxDCBase::Rotate( wxList* points, double angle, wxPoint center ) double pi(M_PI); double dSinA = -sin(angle*2.0*pi/360.0); double dCosA = cos(angle*2.0*pi/360.0); - for ( wxNode* node = points->First(); node; node = node->Next() ) + for ( wxNode* node = points->GetFirst(); node; node = node->GetNext() ) { - wxPoint* point = (wxPoint*)node->Data(); + wxPoint* point = (wxPoint*)node->GetData(); // transform coordinates, if necessary if( center.x ) point->x -= center.x; @@ -1062,14 +1071,14 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, bool bForceTurn = ( sq == eq && sa > ea ); while( !bReady ) { - for( wxNode *node = pointsarray[q].First(); node; node = node->Next() ) + for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() ) { // once: go to starting point in start quadrant if( !bStarted && ( - ( (wxPoint*) node->Data() )->x < xsa+1 && q <= 1 + ( (wxPoint*) node->GetData() )->x < xsa+1 && q <= 1 || - ( (wxPoint*) node->Data() )->x > xsa-1 && q >= 2 + ( (wxPoint*) node->GetData() )->x > xsa-1 && q >= 2 ) ) { @@ -1081,16 +1090,16 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, { if( q != eq || bForceTurn || - ( (wxPoint*) node->Data() )->x > xea+1 && q <= 1 + ( (wxPoint*) node->GetData() )->x > xea+1 && q <= 1 || - ( (wxPoint*) node->Data() )->x < xea-1 && q >= 2 + ( (wxPoint*) node->GetData() )->x < xea-1 && q >= 2 ) { // copy point - wxPoint* pPoint = new wxPoint( *((wxPoint*) node->Data() ) ); + wxPoint* pPoint = new wxPoint( *((wxPoint*) node->GetData() ) ); points->Append( (wxObject*) pPoint ); } - else if( q == eq && !bForceTurn || ( (wxPoint*) node->Data() )->x == xea) + else if( q == eq && !bForceTurn || ( (wxPoint*) node->GetData() )->x == xea) { bReady = true; } @@ -1106,9 +1115,9 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, // delete points for( q = 0; q < 4; ++q ) { - for( wxNode *node = pointsarray[q].First(); node; node = node->Next() ) + for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() ) { - wxPoint *p = (wxPoint *)node->Data(); + wxPoint *p = (wxPoint *)node->GetData(); delete p; } } @@ -1117,24 +1126,24 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, { wxNode* node; // copy whole ellipse, wxPoints will be deleted outside - for( node = pointsarray[0].First(); node; node = node->Next() ) + for( node = pointsarray[0].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxObject *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[1].First(); node; node = node->Next() ) + for( node = pointsarray[1].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxObject *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[2].First(); node; node = node->Next() ) + for( node = pointsarray[2].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxObject *p = node->GetData(); points->Append( p ); } - for( node = pointsarray[3].First(); node; node = node->Next() ) + for( node = pointsarray[3].GetFirst(); node; node = node->GetNext() ) { - wxObject *p = node->Data(); + wxObject *p = node->GetData(); points->Append( p ); } } // not iUseAngles @@ -1142,3 +1151,358 @@ void wxDCBase::CalculateEllipticPoints( wxList* points, #endif +// +// temporary home for wxOverlay +// + +#include "wx/dcclient.h" +#include "wx/dcmemory.h" + +#if defined(wxMAC_USE_CORE_GRAPHICS) && wxMAC_USE_CORE_GRAPHICS + +#include "wx/mac/private.h" +#include "wx/toplevel.h" + +class wxOverlayImpl +{ +public: + wxOverlayImpl() ; + ~wxOverlayImpl() ; + + + // clears the overlay without restoring the former state + // to be done eg when the window content has been changed and repainted + void Reset(); + + // returns true if it has been setup + bool IsOk(); + + void Init( wxWindowDC* dc, int x , int y , int width , int height ); + + void BeginDrawing( wxWindowDC* dc); + + void EndDrawing( wxWindowDC* dc); + + void Clear( wxWindowDC* dc); + +private: + OSStatus CreateOverlayWindow(); + + void MacGetBounds( Rect *bounds ); + + WindowRef m_overlayWindow; + WindowRef m_overlayParentWindow; + CGContextRef m_overlayContext ; + // we store the window in case we would have to issue a Refresh() + wxWindow* m_window ; + + int m_x ; + int m_y ; + int m_width ; + int m_height ; +} ; + +wxOverlayImpl::wxOverlayImpl() +{ + m_window = NULL ; + m_overlayContext = NULL ; + m_overlayWindow = NULL ; +} + +wxOverlayImpl::~wxOverlayImpl() +{ + Reset(); +} + +bool wxOverlayImpl::IsOk() +{ + return m_overlayWindow != NULL ; +} + +void wxOverlayImpl::MacGetBounds( Rect *bounds ) +{ + wxPoint origin(0,0); + origin = m_window->ClientToScreen( origin ); + bounds->top = origin.y; + bounds->left = origin.x; + bounds->bottom = origin.y+m_y+m_height; + bounds->right = origin.x+m_x+m_width; +} + +OSStatus wxOverlayImpl::CreateOverlayWindow() +{ + OSStatus err; + + WindowAttributes overlayAttributes = kWindowIgnoreClicksAttribute; + + m_overlayParentWindow =(WindowRef) m_window->MacGetTopLevelWindowRef(); + + Rect bounds ; + MacGetBounds(&bounds); + err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow ); + if ( err == noErr ) + { + SetWindowGroup( m_overlayWindow, GetWindowGroup(m_overlayParentWindow)); // Put them in the same group so that their window layers are consistent + ShowWindow(m_overlayWindow); + } + return err; +} + +void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height ) +{ + wxASSERT_MSG( !IsOk() , _("You cannot Init an overlay twice") ); + + m_window = dc->GetWindow(); + m_x = x ; + m_y = y ; + m_width = width ; + m_height = height ; + + OSStatus err = CreateOverlayWindow(); + wxASSERT_MSG( err == noErr , _("Couldn't create the overlay window") ); +#ifndef __LP64__ + err = QDBeginCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext); +#endif + CGContextTranslateCTM( m_overlayContext, 0, m_height+m_y ); + CGContextScaleCTM( m_overlayContext, 1, -1 ); + wxASSERT_MSG( err == noErr , _("Couldn't init the context on the overlay window") ); +} + +void wxOverlayImpl::BeginDrawing( wxWindowDC* dc) +{ + delete dc->m_graphicContext ; + dc->m_graphicContext = new wxMacCGContext( m_overlayContext ); + // we are right now startin at 0,0 not at the wxWindow's origin, so most of the calculations + // int dc are already corect + // just to make sure : + dc->m_macLocalOrigin.x = 0 ; + dc->m_macLocalOrigin.y = 0 ; + wxSize size = m_window->GetSize() ; + dc->SetClippingRegion( 0 , 0 , size.x , size.y ) ; +} + +void wxOverlayImpl::EndDrawing( wxWindowDC* dc) +{ + delete dc->m_graphicContext ; + dc->m_graphicContext = NULL ; + +} + +void wxOverlayImpl::Clear(wxWindowDC* dc) +{ + wxASSERT_MSG( IsOk() , _("You cannot Clear an overlay that is not inited") ); + CGRect box = CGRectMake( m_x - 1, m_y - 1 , m_width + 2 , m_height + 2 ); + CGContextClearRect( m_overlayContext, box ); +} + +void wxOverlayImpl::Reset() +{ + if ( m_overlayContext ) + { +#ifndef __LP64__ + OSStatus err = QDEndCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext); + wxASSERT_MSG( err == noErr , _("Couldn't end the context on the overlay window") ); +#endif + m_overlayContext = NULL ; + } + + // todo : don't dispose, only hide and reposition on next run + if (m_overlayWindow) + { + DisposeWindow(m_overlayWindow); + m_overlayWindow = NULL ; + } +} + +// +// +// + +#else // ie not wxMAC_USE_CORE_GRAPHICS + +class wxOverlayImpl +{ +public: + wxOverlayImpl() ; + ~wxOverlayImpl() ; + + + // clears the overlay without restoring the former state + // to be done eg when the window content has been changed and repainted + void Reset(); + + // returns true if it has been setup + bool IsOk(); + + void Init( wxWindowDC* dc, int x , int y , int width , int height ); + + void BeginDrawing( wxWindowDC* dc); + + void EndDrawing( wxWindowDC* dc); + + void Clear( wxWindowDC* dc); + +private: + wxBitmap m_bmpSaved ; + int m_x ; + int m_y ; + int m_width ; + int m_height ; +// this is to enable wxMOTIF and UNIV to compile.... +// currently (10 oct 06) we don't use m_window +// ce - how do we fix this +#if defined(__WXGTK__) || defined(__WXMSW__) +// + wxWindow* m_window ; +#endif +} ; + +wxOverlayImpl::wxOverlayImpl() +{ +#if defined(__WXGTK__) || defined(__WXMSW__) + m_window = NULL ; +#endif + m_x = m_y = m_width = m_height = 0 ; +} + +wxOverlayImpl::~wxOverlayImpl() +{ +} + +bool wxOverlayImpl::IsOk() +{ + return m_bmpSaved.Ok() ; +} + +void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height ) +{ +#if defined(__WXGTK__) + m_window = dc->m_owner; +#else + #if defined (__WXMSW__) + m_window = dc->GetWindow(); + #endif // __WXMSW__ + +#endif + wxMemoryDC dcMem ; + m_bmpSaved.Create( width, height ); + dcMem.SelectObject( m_bmpSaved ); + m_x = x ; + m_y = y ; + m_width = width ; + m_height = height ; +#if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__) + wxPoint pt = dc->GetDeviceOrigin(); + x += pt.x; + y += pt.y; +#endif // broken wxGTK wxDC::Blit + dcMem.Blit(0, 0, m_width, m_height, + dc, x, y); + dcMem.SelectObject( wxNullBitmap ); +} + +void wxOverlayImpl::Clear(wxWindowDC* dc) +{ + wxMemoryDC dcMem ; + dcMem.SelectObject( m_bmpSaved ); + dc->Blit( m_x, m_y, m_width, m_height , &dcMem , 0 , 0 ); + dcMem.SelectObject( wxNullBitmap ); +} + +void wxOverlayImpl::Reset() +{ + m_bmpSaved = wxBitmap(); +} + +void wxOverlayImpl::BeginDrawing(wxWindowDC* WXUNUSED(dc)) +{ +} + +void wxOverlayImpl::EndDrawing(wxWindowDC* WXUNUSED(dc)) +{ +} + +#endif + +// common code + +wxOverlay::wxOverlay() +{ + m_impl = new wxOverlayImpl(); + m_inDrawing = false; +} + +wxOverlay::~wxOverlay() +{ + wxDELETE( m_impl ); +} + +bool wxOverlay::IsOk() +{ + return m_impl->IsOk(); +} + +void wxOverlay::Init( wxWindowDC* dc, int x , int y , int width , int height ) +{ + m_impl->Init(dc, x, y, width, height); +} + +void wxOverlay::BeginDrawing( wxWindowDC* dc) +{ + m_impl->BeginDrawing(dc); + m_inDrawing = true ; +} + +void wxOverlay::EndDrawing( wxWindowDC* dc) +{ + m_impl->EndDrawing(dc); + m_inDrawing = false ; +} + +void wxOverlay::Clear( wxWindowDC* dc) +{ + m_impl->Clear(dc); +} + +void wxOverlay::Reset() +{ + wxASSERT_MSG(m_inDrawing==false,wxT("cannot reset overlay during drawing")); + m_impl->Reset(); +} + +// dc connector + +wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc, int x , int y , int width , int height) : + m_overlay(overlay) +{ + Init(dc, x, y, width, height); +} + +wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc) : + m_overlay(overlay) +{ + int width; + int height; + dc->GetSize(&width,&height); + Init(dc, 0, 0, width, height); +} + +wxDCOverlay::~wxDCOverlay() +{ + m_overlay.EndDrawing(m_dc); +} + +void wxDCOverlay::Init(wxWindowDC *dc, int x , int y , int width , int height ) +{ + m_dc = dc ; + if ( !m_overlay.IsOk() ) + { + m_overlay.Init(dc,x,y,width,height); + } + m_overlay.BeginDrawing(dc); +} + +void wxDCOverlay::Clear() +{ + m_overlay.Clear(m_dc); +}