]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/dcbase.cpp
Updated list of subprojects.
[wxWidgets.git] / src / common / dcbase.cpp
index 4b596ac2f97b87ff675394b1c631ebe75c463ac1..84ac42aa3c6ec51975dfad184a1cae4130d60074 100644 (file)
@@ -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:
 // Purpose:     generic methods of the wxDC Class
 // Author:      Vadim Zeitlin
 // Modified by:
 // declarations
 // ============================================================================
 
 // declarations
 // ============================================================================
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "dcbase.h"
-#endif
-
 // ----------------------------------------------------------------------------
 // headers
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // headers
 // ----------------------------------------------------------------------------
 #endif
 
 #include "wx/dc.h"
 #endif
 
 #include "wx/dc.h"
+#include "wx/dcbuffer.h" // for IMPLEMENT_DYNAMIC_CLASS
+
+#ifndef WX_PRECOMP
+    #include "wx/math.h"
+#endif
 
 // bool wxDCBase::sm_cacheing = false;
 
 
 // bool wxDCBase::sm_cacheing = false;
 
+IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject)
+
 // ============================================================================
 // implementation
 // ============================================================================
 
 // ============================================================================
 // implementation
 // ============================================================================
 
+IMPLEMENT_DYNAMIC_CLASS(wxBufferedDC, wxMemoryDC)
+IMPLEMENT_ABSTRACT_CLASS(wxBufferedPaintDC, wxBufferedDC)
+
+#if WXWIN_COMPATIBILITY_2_6
+void wxDCBase::BeginDrawing()
+{
+}
+
+void wxDCBase::EndDrawing()
+{
+}
+#endif // WXWIN_COMPATIBILITY_2_6
+
 // ----------------------------------------------------------------------------
 // special symbols
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // special symbols
 // ----------------------------------------------------------------------------
@@ -314,7 +330,7 @@ void wxDCBase::DoDrawSpline( wxList *points )
     double           x1, y1, x2, y2;
 
     wxList::compatibility_iterator node = points->GetFirst();
     double           x1, y1, x2, y2;
 
     wxList::compatibility_iterator node = points->GetFirst();
-    if (node == NULL)
+    if (node == wxList::compatibility_iterator())
         // empty list
         return;
 
         // empty list
         return;
 
@@ -373,7 +389,7 @@ void wxDCBase::DoDrawSpline( wxList *points )
 
 
 // Each element of the widths array will be the width of the string up to and
 
 
 // Each element of the widths array will be the width of the string up to and
-// including the coresponding character in text.  This is the generic
+// including the corresponding character in text.  This is the generic
 // implementation, the port-specific classes should do this with native APIs
 // if available and if faster.  Note: pango_layout_index_to_pos is much slower
 // than calling GetTextExtent!!
 // implementation, the port-specific classes should do this with native APIs
 // if available and if faster.  Note: pango_layout_index_to_pos is much slower
 // than calling GetTextExtent!!
@@ -405,15 +421,14 @@ bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths)
 {
     int totalWidth = 0;
 
 {
     int totalWidth = 0;
 
-    size_t i, len = text.Length();
+    const size_t len = text.length();
     widths.Empty();
     widths.Add(0, len);
     widths.Empty();
     widths.Add(0, len);
-    int w, h;
 
     // reset the cache if font or horizontal scale have changed
 
     // reset the cache if font or horizontal scale have changed
-    if (!s_fontWidthCache.m_widths ||
-        (s_fontWidthCache.m_scaleX != m_scaleX) ||
-        (s_fontWidthCache.m_font != GetFont()))
+    if ( !s_fontWidthCache.m_widths ||
+         !wxIsSameDouble(s_fontWidthCache.m_scaleX, m_scaleX) ||
+         (s_fontWidthCache.m_font != GetFont()) )
     {
         s_fontWidthCache.Reset();
         s_fontWidthCache.m_font = GetFont();
     {
         s_fontWidthCache.Reset();
         s_fontWidthCache.m_font = GetFont();
@@ -422,7 +437,8 @@ bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths)
 
     // Calculate the position of each character based on the widths of
     // the previous characters
 
     // Calculate the position of each character based on the widths of
     // the previous characters
-    for (i=0; i<len; i++)
+    int w, h;
+    for ( size_t i = 0; i < len; i++ )
     {
         const wxChar c = text[i];
         unsigned int c_int = (unsigned int)c;
     {
         const wxChar c = text[i];
         unsigned int c_int = (unsigned int)c;
@@ -673,6 +689,156 @@ void wxDCBase::DrawLabel(const wxString& text,
     CalcBoundingBox(x0 + width0, y0 + height);
 }
 
     CalcBoundingBox(x0 + width0, y0 + height);
 }
 
+
+void wxDCBase::DoGradientFillLinear(const wxRect& rect,
+                                    const wxColour& initialColour,
+                                    const wxColour& destColour,
+                                    wxDirection nDirection)
+{
+    // save old pen
+    wxPen oldPen = m_pen;
+
+    wxUint8 nR1 = destColour.Red();
+    wxUint8 nG1 = destColour.Green();
+    wxUint8 nB1 = destColour.Blue();
+    wxUint8 nR2 = initialColour.Red();
+    wxUint8 nG2 = initialColour.Green();
+    wxUint8 nB2 = initialColour.Blue();
+    wxUint8 nR, nG, nB;
+
+    if ( nDirection == wxEAST || nDirection == wxWEST )
+    {
+        wxInt32 x = rect.GetWidth();
+        wxInt32 w = x;              // width of area to shade
+        wxInt32 xDelta = w/256;     // height of one shade bend
+        if (xDelta < 1)
+            xDelta = 1;
+
+        while (x >= xDelta)
+        {
+            x -= xDelta;
+            if (nR1 > nR2)
+                nR = nR1 - (nR1-nR2)*(w-x)/w;
+            else
+                nR = nR1 + (nR2-nR1)*(w-x)/w;
+
+            if (nG1 > nG2)
+                nG = nG1 - (nG1-nG2)*(w-x)/w;
+            else
+                nG = nG1 + (nG2-nG1)*(w-x)/w;
+
+            if (nB1 > nB2)
+                nB = nB1 - (nB1-nB2)*(w-x)/w;
+            else
+                nB = nB1 + (nB2-nB1)*(w-x)/w;
+
+            SetPen(wxPen(wxColour(nR, nG, nB), 1, wxSOLID));
+            if(nDirection == wxEAST)
+                DrawRectangle(rect.GetLeft()+x, rect.GetTop(),
+                        xDelta, rect.GetHeight());
+            else //nDirection == wxWEST
+                DrawRectangle(rect.GetRight()-x-xDelta, rect.GetTop(),
+                        xDelta, rect.GetHeight());
+        }
+    }
+    else  // nDirection == wxNORTH || nDirection == wxSOUTH
+    {
+        wxInt32 y = rect.GetHeight();
+        wxInt32 w = y;              // height of area to shade
+        wxInt32 yDelta = w/255;     // height of one shade bend
+        if (yDelta < 1)
+            yDelta = 1;
+
+        while (y > 0)
+        {
+            y -= yDelta;
+            if (nR1 > nR2)
+                nR = nR1 - (nR1-nR2)*(w-y)/w;
+            else
+                nR = nR1 + (nR2-nR1)*(w-y)/w;
+
+            if (nG1 > nG2)
+                nG = nG1 - (nG1-nG2)*(w-y)/w;
+            else
+                nG = nG1 + (nG2-nG1)*(w-y)/w;
+
+            if (nB1 > nB2)
+                nB = nB1 - (nB1-nB2)*(w-y)/w;
+            else
+                nB = nB1 + (nB2-nB1)*(w-y)/w;
+
+            SetPen(wxPen(wxColour(nR, nG, nB), 1, wxSOLID));
+            if(nDirection == wxNORTH)
+                DrawRectangle(rect.GetLeft(), rect.GetTop()+y,
+                        rect.GetWidth(), yDelta);
+            else //nDirection == wxSOUTH
+                DrawRectangle(rect.GetLeft(), rect.GetBottom()-y-yDelta,
+                        rect.GetWidth(), yDelta);
+        }
+    }
+
+    SetPen(oldPen);
+}
+
+void wxDCBase::DoGradientFillConcentric(const wxRect& rect,
+                                      const wxColour& initialColour,
+                                      const wxColour& destColour,
+                                      const wxPoint& circleCenter)
+{
+    //save the old pen color
+    wxColour oldPenColour = m_pen.GetColour();
+
+    wxUint8 nR1 = destColour.Red();
+    wxUint8 nG1 = destColour.Green();
+    wxUint8 nB1 = destColour.Blue();
+    wxUint8 nR2 = initialColour.Red();
+    wxUint8 nG2 = initialColour.Green();
+    wxUint8 nB2 = initialColour.Blue();
+    wxUint8 nR, nG, nB;
+
+
+    //Radius
+    wxInt32 cx = rect.GetWidth() / 2;
+    wxInt32 cy = rect.GetHeight() / 2;
+    wxInt32 nRadius;
+    if (cx < cy)
+        nRadius = cx;
+    else
+        nRadius = cy;
+
+    //Offset of circle
+    wxInt32 nCircleOffX = circleCenter.x - (rect.GetWidth() / 2);
+    wxInt32 nCircleOffY = circleCenter.y - (rect.GetHeight() / 2);
+
+    for ( wxInt32 x = 0; x < rect.GetWidth(); x++ )
+    {
+        for ( wxInt32 y = 0; y < rect.GetHeight(); y++ )
+        {
+            //get color difference
+            wxInt32 nGradient = ((nRadius -
+                                  (wxInt32)sqrt(
+                                    pow((double)(x - cx - nCircleOffX), 2) +
+                                    pow((double)(y - cy - nCircleOffY), 2)
+                                  )) * 100) / nRadius;
+
+            //normalize Gradient
+            if (nGradient < 0 )
+                nGradient = 0;
+
+            //get dest colors
+            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));
+            DrawPoint(wxPoint(x + rect.GetLeft(), y + rect.GetTop()));
+        }
+    }
+    //return old pen color
+    m_pen.SetColour(oldPenColour);
+}
+
 /*
 Notes for wxWidgets DrawEllipticArcRot(...)
 
 /*
 Notes for wxWidgets DrawEllipticArcRot(...)
 
@@ -728,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
     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;
     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;
         points[i].x = point->x;
         points[i].y = point->y;
         delete point;
@@ -767,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);
         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;
 
             // transform coordinates, if necessary
             if( center.x ) point->x -= center.x;
@@ -905,14 +1071,14 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
         bool bForceTurn = ( sq == eq && sa > ea );
         while( !bReady )
         {
         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 &&
                     (
             {
                 // 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
                     )
                   )
                 {
                     )
                   )
                 {
@@ -924,16 +1090,16 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
                 {
                     if( q != eq || bForceTurn
                         ||
                 {
                     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
                       )
                     {
                         // copy point
-                        wxPoint* pPoint = new wxPoint( *((wxPoint*) node->Data() ) );
+                        wxPoint* pPoint = new wxPoint( *((wxPoint*) node->GetData() ) );
                         points->Append( (wxObject*) pPoint );
                     }
                         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;
                     }
                     {
                         bReady = true;
                     }
@@ -949,34 +1115,35 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
         // delete points
         for( q = 0; q < 4; ++q )
         {
         // 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;
             }
         }
     }
     else
     {
                 delete p;
             }
         }
     }
     else
     {
+        wxNode* node;
         // copy whole ellipse, wxPoints will be deleted outside
         // copy whole ellipse, wxPoints will be deleted outside
-        for( wxNode *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 );
         }
             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 );
         }
             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 );
         }
             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
             points->Append( p );
         }
     } // not iUseAngles
@@ -984,3 +1151,358 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
 
 #endif
 
 
 #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);
+}