]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/dcbase.cpp
use guard classes automatically restoring the old state in their dtor instead of...
[wxWidgets.git] / src / common / dcbase.cpp
index 7f1b5170ec5ae8db0b75218d44e14f05e81ed330..a60da2e6573e8329c69cb9fb4ded229916af23e1 100644 (file)
@@ -1,11 +1,11 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        common/dcbase.cpp
+// Name:        src/common/dcbase.cpp
 // Purpose:     generic methods of the wxDC Class
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:     05/25/99
 // RCS-ID:      $Id$
 // Purpose:     generic methods of the wxDC Class
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:     05/25/99
 // RCS-ID:      $Id$
-// Copyright:   (c) wxWindows team
+// Copyright:   (c) wxWidgets team
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // 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/dcclient.h"
+#include "wx/dcmemory.h"
+#include "wx/dcscreen.h"
+#include "wx/dcprint.h"
+#include "wx/prntbase.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/math.h"
+    #include "wx/module.h"
+#endif
 
 
-#include <math.h>
+#ifdef __WXMSW__
+    #include "wx/msw/dcclient.h"
+    #include "wx/msw/dcmemory.h"
+    #include "wx/msw/dcscreen.h"
+#endif
 
 
-// bool wxDCBase::sm_cacheing = FALSE;
+#ifdef __WXGTK20__
+    #include "wx/gtk/dcclient.h"
+    #include "wx/gtk/dcmemory.h"
+    #include "wx/gtk/dcscreen.h"
+#elif defined(__WXGTK__)
+    #include "wx/gtk1/dcclient.h"
+    #include "wx/gtk1/dcmemory.h"
+    #include "wx/gtk1/dcscreen.h"
+#endif
 
 
-// ============================================================================
-// implementation
-// ============================================================================
+#ifdef __WXMAC__
+    #include "wx/osx/dcclient.h"
+    #include "wx/osx/dcmemory.h"
+    #include "wx/osx/dcscreen.h"
+#endif
+
+#ifdef __WXPM__
+    #include "wx/os2/dcclient.h"
+    #include "wx/os2/dcmemory.h"
+    #include "wx/os2/dcscreen.h"
+#endif
+
+#ifdef __WXCOCOA__
+    #include "wx/cocoa/dcclient.h"
+    #include "wx/cocoa/dcmemory.h"
+    #include "wx/cocoa/dcscreen.h"
+#endif
+
+#ifdef __WXMOTIF__
+    #include "wx/motif/dcclient.h"
+    #include "wx/motif/dcmemory.h"
+    #include "wx/motif/dcscreen.h"
+#endif
+
+#ifdef __WXX11__
+    #include "wx/x11/dcclient.h"
+    #include "wx/x11/dcmemory.h"
+    #include "wx/x11/dcscreen.h"
+#endif
+
+#ifdef __WXDFB__
+    #include "wx/dfb/dcclient.h"
+    #include "wx/dfb/dcmemory.h"
+    #include "wx/dfb/dcscreen.h"
+#endif
+
+#ifdef __WXPALMOS__
+    #include "wx/palmos/dcclient.h"
+    #include "wx/palmos/dcmemory.h"
+    #include "wx/palmos/dcscreen.h"
+#endif
+
+//----------------------------------------------------------------------------
+// wxDCFactory
+//----------------------------------------------------------------------------
+
+wxDCFactory *wxDCFactory::m_factory = NULL;
+
+void wxDCFactory::Set(wxDCFactory *factory)
+{
+    delete m_factory;
+
+    m_factory = factory;
+}
+
+wxDCFactory *wxDCFactory::Get()
+{
+    if ( !m_factory )
+        m_factory = new wxNativeDCFactory;
+
+    return m_factory;
+}
+
+class wxDCFactoryCleanupModule : public wxModule
+{
+public:
+    virtual bool OnInit() { return true; }
+    virtual void OnExit() { wxDCFactory::Set(NULL); }
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxDCFactoryCleanupModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxDCFactoryCleanupModule, wxModule)
+
+//-----------------------------------------------------------------------------
+// wxNativeDCFactory
+//-----------------------------------------------------------------------------
+
+wxDCImpl* wxNativeDCFactory::CreateWindowDC( wxWindowDC *owner, wxWindow *window )
+{
+    wxDCImpl * const impl = new wxWindowDCImpl( owner, window );
+    impl->InheritAttributes(window);
+    return impl;
+}
+
+wxDCImpl* wxNativeDCFactory::CreateClientDC( wxClientDC *owner, wxWindow *window )
+{
+    wxDCImpl * const impl = new wxClientDCImpl( owner, window );
+    impl->InheritAttributes(window);
+    return impl;
+}
+
+wxDCImpl* wxNativeDCFactory::CreatePaintDC( wxPaintDC *owner, wxWindow *window )
+{
+    wxDCImpl * const impl = new wxPaintDCImpl( owner, window );
+    impl->InheritAttributes(window);
+    return impl;
+}
+
+wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner )
+{
+    return new wxMemoryDCImpl( owner );
+}
+
+wxDCImpl* wxNativeDCFactory::CreateMemoryDC(wxMemoryDC *owner, wxBitmap& bitmap)
+{
+    // the bitmap may be modified when it's selected into a memory DC so make
+    // sure changing this bitmap doesn't affect any other shallow copies of it
+    // (see wxMemoryDC::SelectObject())
+    //
+    // notice that we don't provide any ctor equivalent to SelectObjectAsSource
+    // method because this should be rarely needed and easy to work around by
+    // using the default ctor and calling SelectObjectAsSource itself
+    if ( bitmap.IsOk() )
+        bitmap.UnShare();
+
+    return new wxMemoryDCImpl(owner, bitmap);
+}
+
+wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner, wxDC *dc )
+{
+    return new wxMemoryDCImpl( owner, dc );
+}
+
+wxDCImpl* wxNativeDCFactory::CreateScreenDC( wxScreenDC *owner )
+{
+    return new wxScreenDCImpl( owner );
+}
+
+#if wxUSE_PRINTING_ARCHITECTURE
+wxDCImpl *wxNativeDCFactory::CreatePrinterDC( wxPrinterDC *owner, const wxPrintData &data )
+{
+    wxPrintFactory *factory = wxPrintFactory::GetFactory();
+    return factory->CreatePrinterDCImpl( owner, data );
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// wxWindowDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxWindowDC, wxDC)
+
+wxWindowDC::wxWindowDC(wxWindow *win)
+          : wxDC(wxDCFactory::Get()->CreateWindowDC(this, win))
+{
+}
+
+//-----------------------------------------------------------------------------
+// wxClientDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxClientDC, wxWindowDC)
+
+wxClientDC::wxClientDC(wxWindow *win)
+          : wxWindowDC(wxDCFactory::Get()->CreateClientDC(this, win))
+{
+}
+
+//-----------------------------------------------------------------------------
+// wxMemoryDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC, wxDC)
+
+wxMemoryDC::wxMemoryDC()
+          : wxDC(wxDCFactory::Get()->CreateMemoryDC(this))
+{
+}
+
+wxMemoryDC::wxMemoryDC(wxBitmap& bitmap)
+          : wxDC(wxDCFactory::Get()->CreateMemoryDC(this, bitmap))
+{
+}
+
+wxMemoryDC::wxMemoryDC(wxDC *dc)
+          : wxDC(wxDCFactory::Get()->CreateMemoryDC(this, dc))
+{
+}
+
+void wxMemoryDC::SelectObject(wxBitmap& bmp)
+{
+    // make sure that the given wxBitmap is not sharing its data with other
+    // wxBitmap instances as its contents will be modified by any drawing
+    // operation done on this DC
+    if (bmp.IsOk())
+        bmp.UnShare();
+
+    GetImpl()->DoSelect(bmp);
+}
+
+void wxMemoryDC::SelectObjectAsSource(const wxBitmap& bmp)
+{
+    GetImpl()->DoSelect(bmp);
+}
+
+const wxBitmap& wxMemoryDC::GetSelectedBitmap() const
+{
+    return GetImpl()->GetSelectedBitmap();
+}
+
+wxBitmap& wxMemoryDC::GetSelectedBitmap()
+{
+    return GetImpl()->GetSelectedBitmap();
+}
+
+
+//-----------------------------------------------------------------------------
+// wxPaintDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxPaintDC, wxClientDC)
+
+wxPaintDC::wxPaintDC(wxWindow *win)
+         : wxClientDC(wxDCFactory::Get()->CreatePaintDC(this, win))
+{
+}
+
+//-----------------------------------------------------------------------------
+// wxScreenDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxScreenDC, wxWindowDC)
+
+wxScreenDC::wxScreenDC()
+          : wxDC(wxDCFactory::Get()->CreateScreenDC(this))
+{
+}
+
+//-----------------------------------------------------------------------------
+// wxPrinterDC
+//-----------------------------------------------------------------------------
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+IMPLEMENT_DYNAMIC_CLASS(wxPrinterDC, wxDC)
+
+wxPrinterDC::wxPrinterDC()
+           : wxDC(wxDCFactory::Get()->CreatePrinterDC(this, wxPrintData()))
+{
+}
+
+wxPrinterDC::wxPrinterDC(const wxPrintData& data)
+           : wxDC(wxDCFactory::Get()->CreatePrinterDC(this, data))
+{
+}
+
+wxRect wxPrinterDC::GetPaperRect() const
+{
+    return GetImpl()->GetPaperRect();
+}
+
+int wxPrinterDC::GetResolution() const
+{
+    return GetImpl()->GetResolution();
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+//-----------------------------------------------------------------------------
+// wxDCImpl
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxDCImpl, wxObject)
+
+wxDCImpl::wxDCImpl( wxDC *owner )
+        : m_window(NULL)
+        , m_colour(wxColourDisplay())
+        , m_ok(true)
+        , m_clipping(false)
+        , m_isInteractive(0)
+        , m_isBBoxValid(false)
+        , m_logicalOriginX(0), m_logicalOriginY(0)
+        , m_deviceOriginX(0), m_deviceOriginY(0)
+        , m_deviceLocalOriginX(0), m_deviceLocalOriginY(0)
+        , m_logicalScaleX(1.0), m_logicalScaleY(1.0)
+        , m_userScaleX(1.0), m_userScaleY(1.0)
+        , m_scaleX(1.0), m_scaleY(1.0)
+        , m_signX(1), m_signY(1)
+        , m_minX(0), m_minY(0), m_maxX(0), m_maxY(0)
+        , m_clipX1(0), m_clipY1(0), m_clipX2(0), m_clipY2(0)
+        , m_logicalFunction(wxCOPY)
+        , m_backgroundMode(wxBRUSHSTYLE_TRANSPARENT)
+        , m_mappingMode(wxMM_TEXT)
+        , m_pen()
+        , m_brush()
+        , m_backgroundBrush()
+        , m_textForegroundColour(*wxBLACK)
+        , m_textBackgroundColour(*wxWHITE)
+        , m_font()
+#if wxUSE_PALETTE
+        , m_palette()
+        , m_hasCustomPalette(false)
+#endif // wxUSE_PALETTE
+{
+    m_owner = owner;
+
+    m_mm_to_pix_x = (double)wxGetDisplaySize().GetWidth() /
+                    (double)wxGetDisplaySizeMM().GetWidth();
+    m_mm_to_pix_y = (double)wxGetDisplaySize().GetHeight() /
+                    (double)wxGetDisplaySizeMM().GetHeight();
+
+    ResetBoundingBox();
+    ResetClipping();
+}
+
+wxDCImpl::~wxDCImpl()
+{
+}
 
 // ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
-// special symbols
+// coordinate conversions and transforms
 // ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
 
-void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1,
+wxCoord wxDCImpl::DeviceToLogicalX(wxCoord x) const
+{
+    return wxRound( (double)((x - m_deviceOriginX - m_deviceLocalOriginX) * m_signX) / m_scaleX ) + m_logicalOriginX ;
+}
+
+wxCoord wxDCImpl::DeviceToLogicalY(wxCoord y) const
+{
+    return wxRound( (double)((y - m_deviceOriginY - m_deviceLocalOriginY) * m_signY) / m_scaleY ) + m_logicalOriginY ;
+}
+
+wxCoord wxDCImpl::DeviceToLogicalXRel(wxCoord x) const
+{
+    return wxRound((double)(x) / m_scaleX);
+}
+
+wxCoord wxDCImpl::DeviceToLogicalYRel(wxCoord y) const
+{
+    return wxRound((double)(y) / m_scaleY);
+}
+
+wxCoord wxDCImpl::LogicalToDeviceX(wxCoord x) const
+{
+    return wxRound( (double)((x - m_logicalOriginX) * m_signX) * m_scaleX) + m_deviceOriginX + m_deviceLocalOriginX;
+}
+
+wxCoord wxDCImpl::LogicalToDeviceY(wxCoord y) const
+{
+    return wxRound( (double)((y - m_logicalOriginY) * m_signY) * m_scaleY) + m_deviceOriginY + m_deviceLocalOriginY;
+}
+
+wxCoord wxDCImpl::LogicalToDeviceXRel(wxCoord x) const
+{
+    return wxRound((double)(x) * m_scaleX);
+}
+
+wxCoord wxDCImpl::LogicalToDeviceYRel(wxCoord y) const
+{
+    return wxRound((double)(y) * m_scaleY);
+}
+
+void wxDCImpl::ComputeScaleAndOrigin()
+{
+    m_scaleX = m_logicalScaleX * m_userScaleX;
+    m_scaleY = m_logicalScaleY * m_userScaleY;
+}
+
+void wxDCImpl::SetMapMode( int mode )
+{
+    switch (mode)
+    {
+        case wxMM_TWIPS:
+          SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
+          break;
+        case wxMM_POINTS:
+          SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
+          break;
+        case wxMM_METRIC:
+          SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
+          break;
+        case wxMM_LOMETRIC:
+          SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
+          break;
+        default:
+        case wxMM_TEXT:
+          SetLogicalScale( 1.0, 1.0 );
+          break;
+    }
+    m_mappingMode = mode;
+}
+
+void wxDCImpl::SetUserScale( double x, double y )
+{
+    // allow negative ? -> no
+    m_userScaleX = x;
+    m_userScaleY = y;
+    ComputeScaleAndOrigin();
+}
+
+void wxDCImpl::SetLogicalScale( double x, double y )
+{
+    // allow negative ?
+    m_logicalScaleX = x;
+    m_logicalScaleY = y;
+    ComputeScaleAndOrigin();
+}
+
+void wxDCImpl::SetLogicalOrigin( wxCoord x, wxCoord y )
+{
+    m_logicalOriginX = x * m_signX;
+    m_logicalOriginY = y * m_signY;
+    ComputeScaleAndOrigin();
+}
+
+void wxDCImpl::SetDeviceOrigin( wxCoord x, wxCoord y )
+{
+    m_deviceOriginX = x;
+    m_deviceOriginY = y;
+    ComputeScaleAndOrigin();
+}
+
+void wxDCImpl::SetDeviceLocalOrigin( wxCoord x, wxCoord y )
+{
+    m_deviceLocalOriginX = x;
+    m_deviceLocalOriginY = y;
+    ComputeScaleAndOrigin();
+}
+
+void wxDCImpl::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
+{
+    // only wxPostScripDC has m_signX = -1, we override SetAxisOrientation there
+    // wxWidgets 2.9: no longer override it
+    m_signX = (xLeftRight ?  1 : -1);
+    m_signY = (yBottomUp  ? -1 :  1);
+    ComputeScaleAndOrigin();
+}
+
+
+// Each element of the widths array will be the width of the string up to and
+// 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!!
+
+#define FWC_SIZE 256
+
+class FontWidthCache
+{
+public:
+    FontWidthCache() : m_scaleX(1), m_widths(NULL) { }
+    ~FontWidthCache() { delete []m_widths; }
+
+    void Reset()
+    {
+        if (!m_widths)
+            m_widths = new int[FWC_SIZE];
+
+        memset(m_widths, 0, sizeof(int)*FWC_SIZE);
+    }
+
+    wxFont m_font;
+    double m_scaleX;
+    int *m_widths;
+};
+
+static FontWidthCache s_fontWidthCache;
+
+bool wxDCImpl::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
+{
+    int totalWidth = 0;
+
+    const size_t len = text.length();
+    widths.Empty();
+    widths.Add(0, len);
+
+    // reset the cache if font or horizontal scale have changed
+    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.m_scaleX = m_scaleX;
+    }
+
+    // Calculate the position of each character based on the widths of
+    // the previous characters
+    int w, h;
+    for ( size_t i = 0; i < len; i++ )
+    {
+        const wxChar c = text[i];
+        unsigned int c_int = (unsigned int)c;
+
+        if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0))
+        {
+            w = s_fontWidthCache.m_widths[c_int];
+        }
+        else
+        {
+            DoGetTextExtent(c, &w, &h);
+            if (c_int < FWC_SIZE)
+                s_fontWidthCache.m_widths[c_int] = w;
+        }
+
+        totalWidth += w;
+        widths[i] = totalWidth;
+    }
+
+    return true;
+}
+
+void wxDCImpl::GetMultiLineTextExtent(const wxString& text,
+                                      wxCoord *x,
+                                      wxCoord *y,
+                                      wxCoord *h,
+                                      const wxFont *font) const
+{
+    wxCoord widthTextMax = 0, widthLine,
+            heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
+
+    wxString curLine;
+    for ( wxString::const_iterator pc = text.begin(); ; ++pc )
+    {
+        if ( pc == text.end() || *pc == _T('\n') )
+        {
+            if ( curLine.empty() )
+            {
+                // we can't use GetTextExtent - it will return 0 for both width
+                // and height and an empty line should count in height
+                // calculation
+
+                // assume that this line has the same height as the previous
+                // one
+                if ( !heightLineDefault )
+                    heightLineDefault = heightLine;
+
+                if ( !heightLineDefault )
+                {
+                    // but we don't know it yet - choose something reasonable
+                    DoGetTextExtent(_T("W"), NULL, &heightLineDefault,
+                                  NULL, NULL, font);
+                }
+
+                heightTextTotal += heightLineDefault;
+            }
+            else
+            {
+                DoGetTextExtent(curLine, &widthLine, &heightLine,
+                              NULL, NULL, font);
+                if ( widthLine > widthTextMax )
+                    widthTextMax = widthLine;
+                heightTextTotal += heightLine;
+            }
+
+            if ( pc == text.end() )
+            {
+               break;
+            }
+            else // '\n'
+            {
+               curLine.clear();
+            }
+        }
+        else
+        {
+            curLine += *pc;
+        }
+    }
+
+    if ( x )
+        *x = widthTextMax;
+    if ( y )
+        *y = heightTextTotal;
+    if ( h )
+        *h = heightLine;
+}
+
+void wxDCImpl::DoDrawCheckMark(wxCoord x1, wxCoord y1,
                                wxCoord width, wxCoord height)
 {
                                wxCoord width, wxCoord height)
 {
-    wxCHECK_RET( Ok(), wxT("invalid window dc") );
+    wxCHECK_RET( IsOk(), wxT("invalid window dc") );
 
     wxCoord x2 = x1 + width,
             y2 = y1 + height;
 
 
     wxCoord x2 = x1 + width,
             y2 = y1 + height;
 
-    // this is to yield width of 3 for width == height == 10
-    SetPen(wxPen(GetTextForeground(), (width + height + 1) / 7, wxSOLID));
+    // the pen width is calibrated to give 3 for width == height == 10
+    wxDCPenChanger pen( *m_owner, wxPen(GetTextForeground(), (width + height + 1)/7));
 
     // we're drawing a scaled version of wx/generic/tick.xpm here
     wxCoord x3 = x1 + (4*width) / 10,   // x of the tick bottom
 
     // we're drawing a scaled version of wx/generic/tick.xpm here
     wxCoord x3 = x1 + (4*width) / 10,   // x of the tick bottom
@@ -63,19 +644,47 @@ void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1,
     CalcBoundingBox(x2, y2);
 }
 
     CalcBoundingBox(x2, y2);
 }
 
-// ----------------------------------------------------------------------------
-// line/polygons
-// ----------------------------------------------------------------------------
+bool
+wxDCImpl::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( srcWidth && srcHeight && dstWidth && dstHeight, false,
+                 _T("invalid blit size") );
+
+    // emulate the stretching by modifying the DC scale
+    double xscale = (double)srcWidth/dstWidth,
+           yscale = (double)srcHeight/dstHeight;
+
+    double xscaleOld, yscaleOld;
+    GetUserScale(&xscaleOld, &yscaleOld);
+    SetUserScale(xscaleOld/xscale, yscaleOld/yscale);
 
 
-void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset)
+    bool rc = DoBlit(wxCoord(xdest*xscale), wxCoord(ydest*yscale),
+                     wxCoord(dstWidth*xscale), wxCoord(dstHeight*yscale),
+                     source,
+                     xsrc, ysrc, rop, useMask, xsrcMask, ysrcMask);
+
+    SetUserScale(xscaleOld, yscaleOld);
+
+    return rc;
+}
+
+void wxDCImpl::DrawLines(const wxPointList *list, wxCoord xoffset, wxCoord yoffset)
 {
     int n = list->GetCount();
     wxPoint *points = new wxPoint[n];
 
     int i = 0;
 {
     int n = list->GetCount();
     wxPoint *points = new wxPoint[n];
 
     int i = 0;
-    for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
+    for ( wxPointList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
     {
     {
-        wxPoint *point = (wxPoint *)node->GetData();
+        wxPoint *point = node->GetData();
         points[i].x = point->x;
         points[i].y = point->y;
     }
         points[i].x = point->x;
         points[i].y = point->y;
     }
@@ -85,8 +694,7 @@ void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset)
     delete [] points;
 }
 
     delete [] points;
 }
 
-
-void wxDCBase::DrawPolygon(const wxList *list,
+void wxDCImpl::DrawPolygon(const wxPointList *list,
                            wxCoord xoffset, wxCoord yoffset,
                            int fillStyle)
 {
                            wxCoord xoffset, wxCoord yoffset,
                            int fillStyle)
 {
@@ -94,9 +702,9 @@ void wxDCBase::DrawPolygon(const wxList *list,
     wxPoint *points = new wxPoint[n];
 
     int i = 0;
     wxPoint *points = new wxPoint[n];
 
     int i = 0;
-    for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
+    for ( wxPointList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
     {
     {
-        wxPoint *point = (wxPoint *)node->GetData();
+        wxPoint *point = node->GetData();
         points[i].x = point->x;
         points[i].y = point->y;
     }
         points[i].x = point->x;
         points[i].y = point->y;
     }
@@ -107,15 +715,15 @@ void wxDCBase::DrawPolygon(const wxList *list,
 }
 
 void
 }
 
 void
-wxDCBase::DoDrawPolyPolygon(int n,
-                            int start[],
+wxDCImpl::DoDrawPolyPolygon(int n,
+                            int count[],
                             wxPoint points[],
                             wxCoord xoffset, wxCoord yoffset,
                             int fillStyle)
 {
     if ( n == 1 )
     {
                             wxPoint points[],
                             wxCoord xoffset, wxCoord yoffset,
                             int fillStyle)
 {
     if ( n == 1 )
     {
-        DoDrawPolygon(start[0], points, xoffset, yoffset, fillStyle);
+        DoDrawPolygon(count[0], points, xoffset, yoffset, fillStyle);
         return;
     }
 
         return;
     }
 
@@ -126,68 +734,44 @@ wxDCBase::DoDrawPolyPolygon(int n,
     for (i = j = lastOfs = 0; i < n; i++)
     {
         lastOfs = j;
     for (i = j = lastOfs = 0; i < n; i++)
     {
         lastOfs = j;
-        j      += start[i];
+        j      += count[i];
     }
     pts = new wxPoint[j+n-1];
     for (i = 0; i < j; i++)
         pts[i] = points[i];
     for (i = 2; i <= n; i++)
     {
     }
     pts = new wxPoint[j+n-1];
     for (i = 0; i < j; i++)
         pts[i] = points[i];
     for (i = 2; i <= n; i++)
     {
-        lastOfs -= start[n-i];
+        lastOfs -= count[n-i];
         pts[j++] = pts[lastOfs];
     }
 
     pen = GetPen();
         pts[j++] = pts[lastOfs];
     }
 
     pen = GetPen();
-    SetPen(wxPen(*wxBLACK, 0, wxTRANSPARENT));
+    SetPen(wxPen(*wxBLACK, 0, wxPENSTYLE_TRANSPARENT));
     DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle);
     SetPen(pen);
     for (i = j = 0; i < n; i++)
     {
     DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle);
     SetPen(pen);
     for (i = j = 0; i < n; i++)
     {
-        DoDrawLines(start[i], pts+j, xoffset, yoffset);
-        j += start[i];
+        DoDrawLines(count[i], pts+j, xoffset, yoffset);
+        j += count[i];
     }
     }
-    delete pts;
+    delete[] pts;
 }
 
 }
 
-// ----------------------------------------------------------------------------
-// splines
-// ----------------------------------------------------------------------------
-
 #if wxUSE_SPLINES
 
 #if wxUSE_SPLINES
 
-// TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?)
-void wxDCBase::DrawSpline(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord x3, wxCoord y3)
+void wxDCImpl::DrawSpline(wxCoord x1, wxCoord y1,
+                          wxCoord x2, wxCoord y2,
+                          wxCoord x3, wxCoord y3)
 {
 {
-    wxList point_list;
-
-    wxPoint *point1 = new wxPoint;
-    point1->x = x1; point1->y = y1;
-    point_list.Append((wxObject*)point1);
-
-    wxPoint *point2 = new wxPoint;
-    point2->x = x2; point2->y = y2;
-    point_list.Append((wxObject*)point2);
-
-    wxPoint *point3 = new wxPoint;
-    point3->x = x3; point3->y = y3;
-    point_list.Append((wxObject*)point3);
-
-    DrawSpline(&point_list);
-
-    for( wxList::compatibility_iterator node = point_list.GetFirst(); node; node = node->GetNext() )
-    {
-        wxPoint *p = (wxPoint *)node->GetData();
-        delete p;
-    }
+    wxPoint points[] = { wxPoint(x1, y1), wxPoint(x2, y2), wxPoint(x3, y3) };
+    DrawSpline(WXSIZEOF(points), points);
 }
 
 }
 
-void wxDCBase::DrawSpline(int n, wxPoint points[])
+void wxDCImpl::DrawSpline(int n, wxPoint points[])
 {
 {
-    wxList list;
-    for (int i =0; i < n; i++)
-    {
-        list.Append((wxObject*)&points[i]);
-    }
+    wxPointList list;
+    for ( int i = 0; i < n; i++ )
+        list.Append(&points[i]);
 
     DrawSpline(&list);
 }
 
     DrawSpline(&list);
 }
@@ -202,9 +786,9 @@ int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
           double x4, double y4);
 static bool wx_spline_add_point(double x, double y);
 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
           double x4, double y4);
 static bool wx_spline_add_point(double x, double y);
-static void wx_spline_draw_point_array(wxDCBase *dc);
+static void wx_spline_draw_point_array(wxDC *dc);
 
 
-wxList wx_spline_point_list;
+wxPointList wx_spline_point_list;
 
 #define                half(z1, z2)        ((z1+z2)/2.0)
 #define                THRESHOLD        5
 
 #define                half(z1, z2)        ((z1+z2)/2.0)
 #define                THRESHOLD        5
@@ -287,42 +871,44 @@ int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
 
 static bool wx_spline_add_point(double x, double y)
 {
 
 static bool wx_spline_add_point(double x, double y)
 {
-  wxPoint *point = new wxPoint ;
-  point->x = (int) x;
-  point->y = (int) y;
-  wx_spline_point_list.Append((wxObject*)point);
-  return TRUE;
+    wxPoint *point = new wxPoint( wxRound(x), wxRound(y) );
+    wx_spline_point_list.Append(point );
+    return true;
 }
 
 }
 
-static void wx_spline_draw_point_array(wxDCBase *dc)
+static void wx_spline_draw_point_array(wxDC *dc)
 {
 {
-  dc->DrawLines(&wx_spline_point_list, 0, 0 );
-  wxList::compatibility_iterator node = wx_spline_point_list.GetFirst();
-  while (node)
-  {
-    wxPoint *point = (wxPoint *)node->GetData();
-    delete point;
-    wx_spline_point_list.Erase(node);
-    node = wx_spline_point_list.GetFirst();
-  }
+    dc->DrawLines(&wx_spline_point_list, 0, 0 );
+    wxPointList::compatibility_iterator node = wx_spline_point_list.GetFirst();
+    while (node)
+    {
+        wxPoint *point = node->GetData();
+        delete point;
+        wx_spline_point_list.Erase(node);
+        node = wx_spline_point_list.GetFirst();
+    }
 }
 
 }
 
-void wxDCBase::DoDrawSpline( wxList *points )
+void wxDCImpl::DoDrawSpline( const wxPointList *points )
 {
 {
-    wxCHECK_RET( Ok(), wxT("invalid window dc") );
+    wxCHECK_RET( IsOk(), wxT("invalid window dc") );
 
     wxPoint *p;
     double           cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
     double           x1, y1, x2, y2;
 
 
     wxPoint *p;
     double           cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
     double           x1, y1, x2, y2;
 
-    wxList::compatibility_iterator node = points->GetFirst();
+    wxPointList::compatibility_iterator node = points->GetFirst();
+    if (!node)
+        // empty list
+        return;
+
     p = (wxPoint *)node->GetData();
 
     x1 = p->x;
     y1 = p->y;
 
     node = node->GetNext();
     p = (wxPoint *)node->GetData();
 
     x1 = p->x;
     y1 = p->y;
 
     node = node->GetNext();
-    p = (wxPoint *)node->GetData();
+    p = node->GetData();
 
     x2 = p->x;
     y2 = p->y;
 
     x2 = p->x;
     y2 = p->y;
@@ -339,7 +925,7 @@ void wxDCBase::DoDrawSpline( wxList *points )
 #endif // !wxUSE_STL
           )
     {
 #endif // !wxUSE_STL
           )
     {
-        p = (wxPoint *)node->GetData();
+        p = node->GetData();
         x1 = x2;
         y1 = y2;
         x2 = p->x;
         x1 = x2;
         y1 = y2;
         x2 = p->x;
@@ -360,113 +946,185 @@ void wxDCBase::DoDrawSpline( wxList *points )
     wx_spline_add_point( cx1, cy1 );
     wx_spline_add_point( x2, y2 );
 
     wx_spline_add_point( cx1, cy1 );
     wx_spline_add_point( x2, y2 );
 
-    wx_spline_draw_point_array( this );
+    wx_spline_draw_point_array( m_owner );
 }
 
 #endif // wxUSE_SPLINES
 
 }
 
 #endif // wxUSE_SPLINES
 
-// ----------------------------------------------------------------------------
-// Partial Text Extents
-// ----------------------------------------------------------------------------
-
 
 
-// Each element of the array will be the width of the string up to and
-// including the coresoponding character in text.  This is the generic
-// implementation, the port-specific classes should do this with native APIs
-// if available.
 
 
-bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
+void wxDCImpl::DoGradientFillLinear(const wxRect& rect,
+                                    const wxColour& initialColour,
+                                    const wxColour& destColour,
+                                    wxDirection nDirection)
 {
 {
-    int totalWidth = 0;
-    size_t i;
-
-    widths.Empty();
-    widths.Add(0, text.Length());
-    
-    // Calculate the position of each character based on the widths of
-    // the previous characters
-    for (i=0; i<text.Length(); i++) {
-        int w, h;
-        GetTextExtent(text[i], &w, &h);
-        totalWidth += w;
-        widths[i] = totalWidth;
-    }
-    return true;
-}
-
+    // save old pen
+    wxPen oldPen = m_pen;
+    wxBrush oldBrush = m_brush;
+
+    wxUint8 nR1 = initialColour.Red();
+    wxUint8 nG1 = initialColour.Green();
+    wxUint8 nB1 = initialColour.Blue();
+    wxUint8 nR2 = destColour.Red();
+    wxUint8 nG2 = destColour.Green();
+    wxUint8 nB2 = destColour.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;
 
 
-// ----------------------------------------------------------------------------
-// enhanced text drawing
-// ----------------------------------------------------------------------------
+        while (x >= xDelta)
+        {
+            x -= xDelta;
+            if (nR1 > nR2)
+                nR = nR1 - (nR1-nR2)*(w-x)/w;
+            else
+                nR = nR1 + (nR2-nR1)*(w-x)/w;
 
 
-void wxDCBase::GetMultiLineTextExtent(const wxString& text,
-                                      wxCoord *x,
-                                      wxCoord *y,
-                                      wxCoord *h,
-                                      wxFont *font)
-{
-    wxCoord widthTextMax = 0, widthLine,
-            heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
+            if (nG1 > nG2)
+                nG = nG1 - (nG1-nG2)*(w-x)/w;
+            else
+                nG = nG1 + (nG2-nG1)*(w-x)/w;
 
 
-    wxString curLine;
-    for ( const wxChar *pc = text; ; pc++ )
+            if (nB1 > nB2)
+                nB = nB1 - (nB1-nB2)*(w-x)/w;
+            else
+                nB = nB1 + (nB2-nB1)*(w-x)/w;
+
+            wxColour colour(nR,nG,nB);
+            SetPen(wxPen(colour, 1, wxPENSTYLE_SOLID));
+            SetBrush(wxBrush(colour));
+            if(nDirection == wxEAST)
+                DoDrawRectangle(rect.GetRight()-x-xDelta+1, rect.GetTop(),
+                        xDelta, rect.GetHeight());
+            else //nDirection == wxWEST
+                DoDrawRectangle(rect.GetLeft()+x, rect.GetTop(),
+                        xDelta, rect.GetHeight());
+        }
+    }
+    else  // nDirection == wxNORTH || nDirection == wxSOUTH
     {
     {
-        if ( *pc == _T('\n') || *pc == _T('\0') )
-        {
-            if ( curLine.empty() )
-            {
-                // we can't use GetTextExtent - it will return 0 for both width
-                // and height and an empty line should count in height
-                // calculation
+        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;
 
 
-                // assume that this line has the same height as the previous
-                // one
-                if ( !heightLineDefault )
-                    heightLineDefault = heightLine;
-
-                if ( !heightLineDefault )
-                {
-                    // but we don't know it yet - choose something reasonable
-                    GetTextExtent(_T("W"), NULL, &heightLineDefault,
-                                  NULL, NULL, font);
-                }
+        while (y > 0)
+        {
+            y -= yDelta;
+            if (nR1 > nR2)
+                nR = nR1 - (nR1-nR2)*(w-y)/w;
+            else
+                nR = nR1 + (nR2-nR1)*(w-y)/w;
 
 
-                heightTextTotal += heightLineDefault;
-            }
+            if (nG1 > nG2)
+                nG = nG1 - (nG1-nG2)*(w-y)/w;
             else
             else
-            {
-                GetTextExtent(curLine, &widthLine, &heightLine,
-                              NULL, NULL, font);
-                if ( widthLine > widthTextMax )
-                    widthTextMax = widthLine;
-                heightTextTotal += heightLine;
-            }
+                nG = nG1 + (nG2-nG1)*(w-y)/w;
 
 
-            if ( *pc == _T('\n') )
-            {
-               curLine.clear();
-            }
+            if (nB1 > nB2)
+                nB = nB1 - (nB1-nB2)*(w-y)/w;
             else
             else
-            {
-               // the end of string
-               break;
-            }
+                nB = nB1 + (nB2-nB1)*(w-y)/w;
+
+            wxColour colour(nR,nG,nB);
+            SetPen(wxPen(colour, 1, wxPENSTYLE_SOLID));
+            SetBrush(wxBrush(colour));
+            if(nDirection == wxNORTH)
+                DoDrawRectangle(rect.GetLeft(), rect.GetTop()+y,
+                        rect.GetWidth(), yDelta);
+            else //nDirection == wxSOUTH
+                DoDrawRectangle(rect.GetLeft(), rect.GetBottom()-y-yDelta+1,
+                        rect.GetWidth(), yDelta);
         }
         }
-        else
+    }
+
+    SetPen(oldPen);
+    SetBrush(oldBrush);
+}
+
+void wxDCImpl::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++ )
         {
         {
-            curLine += *pc;
+            //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));
+            DoDrawPoint(x + rect.GetLeft(), y + rect.GetTop());
         }
     }
         }
     }
+    //return old pen color
+    m_pen.SetColour(oldPenColour);
+}
 
 
-    if ( x )
-        *x = widthTextMax;
-    if ( y )
-        *y = heightTextTotal;
-    if ( h )
-        *h = heightLine;
+void wxDCImpl::InheritAttributes(wxWindow *win)
+{
+    wxCHECK_RET( win, "window can't be NULL" );
+
+    SetFont(win->GetFont());
+    SetTextForeground(win->GetForegroundColour());
+    SetTextBackground(win->GetBackgroundColour());
+    SetBackground(wxBrush(win->GetBackgroundColour()));
 }
 
 }
 
-void wxDCBase::DrawLabel(const wxString& text,
+//-----------------------------------------------------------------------------
+// wxDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
+
+void wxDC::DrawLabel(const wxString& text,
                          const wxBitmap& bitmap,
                          const wxRect& rect,
                          int alignment,
                          const wxBitmap& bitmap,
                          const wxRect& rect,
                          int alignment,
@@ -522,7 +1180,7 @@ void wxDCBase::DrawLabel(const wxString& text,
             width0 = width;
     if ( bitmap.Ok() )
     {
             width0 = width;
     if ( bitmap.Ok() )
     {
-        DrawBitmap(bitmap, x, y, TRUE /* use mask */);
+        DrawBitmap(bitmap, x, y, true /* use mask */);
 
         wxCoord offset = bitmap.GetWidth() + 4;
         x += offset;
 
         wxCoord offset = bitmap.GetWidth() + 4;
         x += offset;
@@ -538,9 +1196,9 @@ void wxDCBase::DrawLabel(const wxString& text,
 
     // split the string into lines and draw each of them separately
     wxString curLine;
 
     // split the string into lines and draw each of them separately
     wxString curLine;
-    for ( const wxChar *pc = text; ; pc++ )
+    for ( wxString::const_iterator pc = text.begin(); ; ++pc )
     {
     {
-        if ( *pc == _T('\n') || *pc == _T('\0') )
+        if ( pc == text.end() || *pc == '\n' )
         {
             int xRealStart = x; // init it here to avoid compielr warnings
 
         {
             int xRealStart = x; // init it here to avoid compielr warnings
 
@@ -578,14 +1236,14 @@ void wxDCBase::DrawLabel(const wxString& text,
                 endUnderscore += xRealStart;
             }
 
                 endUnderscore += xRealStart;
             }
 
-            if ( *pc == _T('\0') )
+            if ( pc == text.end() )
                 break;
 
             curLine.clear();
         }
         else // not end of line
         {
                 break;
 
             curLine.clear();
         }
         else // not end of line
         {
-            if ( pc - text.c_str() == indexAccel )
+            if ( pc - text.begin() == indexAccel )
             {
                 // remeber to draw underscore here
                 GetTextExtent(curLine, &startUnderscore, NULL);
             {
                 // remeber to draw underscore here
                 GetTextExtent(curLine, &startUnderscore, NULL);
@@ -605,7 +1263,7 @@ void wxDCBase::DrawLabel(const wxString& text,
     if ( startUnderscore != endUnderscore )
     {
         // it should be of the same colour as text
     if ( startUnderscore != endUnderscore )
     {
         // it should be of the same colour as text
-        SetPen(wxPen(GetTextForeground(), 0, wxSOLID));
+        SetPen(wxPen(GetTextForeground(), 0, wxPENSTYLE_SOLID));
 
         yUnderscore--;
 
 
         yUnderscore--;
 
@@ -622,8 +1280,62 @@ void wxDCBase::DrawLabel(const wxString& text,
     CalcBoundingBox(x0 + width0, y0 + height);
 }
 
     CalcBoundingBox(x0 + width0, y0 + height);
 }
 
+#if WXWIN_COMPATIBILITY_2_8
+    // for compatibility with the old code when wxCoord was long everywhere
+void wxDC::GetTextExtent(const wxString& string,
+                       long *x, long *y,
+                       long *descent,
+                       long *externalLeading,
+                       const wxFont *theFont) const
+    {
+        wxCoord x2, y2, descent2, externalLeading2;
+        m_pimpl->DoGetTextExtent(string, &x2, &y2,
+                        &descent2, &externalLeading2,
+                        theFont);
+        if ( x )
+            *x = x2;
+        if ( y )
+            *y = y2;
+        if ( descent )
+            *descent = descent2;
+        if ( externalLeading )
+            *externalLeading = externalLeading2;
+    }
+
+void wxDC::GetLogicalOrigin(long *x, long *y) const
+    {
+        wxCoord x2, y2;
+        m_pimpl->DoGetLogicalOrigin(&x2, &y2);
+        if ( x )
+            *x = x2;
+        if ( y )
+            *y = y2;
+    }
+
+void wxDC::GetDeviceOrigin(long *x, long *y) const
+    {
+        wxCoord x2, y2;
+        m_pimpl->DoGetDeviceOrigin(&x2, &y2);
+        if ( x )
+            *x = x2;
+        if ( y )
+            *y = y2;
+    }
+
+void wxDC::GetClippingBox(long *x, long *y, long *w, long *h) const
+    {
+        wxCoord xx,yy,ww,hh;
+        m_pimpl->DoGetClippingBox(&xx, &yy, &ww, &hh);
+        if (x) *x = xx;
+        if (y) *y = yy;
+        if (w) *w = ww;
+        if (h) *h = hh;
+    }
+
+#endif  // WXWIN_COMPATIBILITY_2_8
+
 /*
 /*
-Notes for wxWindows DrawEllipticArcRot(...)
+Notes for wxWidgets DrawEllipticArcRot(...)
 
 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
 
 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
@@ -634,19 +1346,19 @@ DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
 methods like (WinCE) wxDC::DoDrawArc(...).
 
 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
 methods like (WinCE) wxDC::DoDrawArc(...).
 
 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
-of an elliptic arc. The algorithm is pixel-based: In every row (in flat 
+of an elliptic arc. The algorithm is pixel-based: In every row (in flat
 parts) or every column (in steep parts) only one pixel is calculated.
 Trigonometric calculation (sin, cos, tan, atan) is only done if the
 parts) or every column (in steep parts) only one pixel is calculated.
 Trigonometric calculation (sin, cos, tan, atan) is only done if the
-starting angle is not equal to the ending angle. The calculation of the 
+starting angle is not equal to the ending angle. The calculation of the
 pixels is done using simple arithmetic only and should perform not too
 bad even on devices without floating point processor. I didn't test this yet.
 
 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
 pixels is done using simple arithmetic only and should perform not too
 bad even on devices without floating point processor. I didn't test this yet.
 
 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
-For instance: an ellipse rotated 180 degrees is drawn 
+For instance: an ellipse rotated 180 degrees is drawn
 slightly different from the original.
 
 slightly different from the original.
 
-The points are then moved to an array and used to draw a polyline and/or polygon 
-(with center added, the pie). 
+The points are then moved to an array and used to draw a polyline and/or polygon
+(with center added, the pie).
 The result looks quite similar to the native ellipse, only e few pixels differ.
 
 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
 The result looks quite similar to the native ellipse, only e few pixels differ.
 
 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
@@ -654,7 +1366,7 @@ slower as DrawEllipse(...), which calls the native API.
 An rotated ellipse outside the clipping region takes nearly the same time,
 while an native ellipse outside takes nearly no time to draw.
 
 An rotated ellipse outside the clipping region takes nearly the same time,
 while an native ellipse outside takes nearly no time to draw.
 
-If you draw an arc with this new method, you will see the starting and ending angles 
+If you draw an arc with this new method, you will see the starting and ending angles
 are calculated properly.
 If you use DrawEllipticArc(...), you will see they are only correct for circles
 and not properly calculated for ellipses.
 are calculated properly.
 If you use DrawEllipticArc(...), you will see they are only correct for circles
 and not properly calculated for ellipses.
@@ -664,26 +1376,26 @@ p.lenhard@t-online.de
 */
 
 #ifdef __WXWINCE__
 */
 
 #ifdef __WXWINCE__
-void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y, 
-                                     wxCoord w, wxCoord h, 
+void wxDCImpl::DoDrawEllipticArcRot( wxCoord x, wxCoord y,
+                                     wxCoord w, wxCoord h,
                                      double sa, double ea, double angle )
 {
                                      double sa, double ea, double angle )
 {
-    wxList list;
+    wxPointList list;
 
     CalculateEllipticPoints( &list, x, y, w, h, sa, ea );
     Rotate( &list, angle, wxPoint( x+w/2, y+h/2 ) );
 
     // Add center (for polygon/pie)
 
     CalculateEllipticPoints( &list, x, y, w, h, sa, ea );
     Rotate( &list, angle, wxPoint( x+w/2, y+h/2 ) );
 
     // Add center (for polygon/pie)
-    list.Append( (wxObject*) new wxPoint( x+w/2, y+h/2 ) );
+    list.Append( new wxPoint( x+w/2, y+h/2 ) );
 
     // copy list into array and delete list elements
 
     // copy list into array and delete list elements
-    int n = list.Number();
+    int n = list.GetCount();
     wxPoint *points = new wxPoint[n];
     int i = 0;
     wxPoint *points = new wxPoint[n];
     int i = 0;
-    wxNode* node = 0;    
-    for ( node = list.First(); node; node = node->Next(), i++ )
+    wxPointList::compatibility_iterator node;
+    for ( node = list.GetFirst(); node; node = node->GetNext(), i++ )
     {
     {
-        wxPoint *point = (wxPoint *)node->Data();
+        wxPoint *point = 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;
@@ -709,17 +1421,18 @@ void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y,
 
 } // DrawEllipticArcRot
 
 
 } // DrawEllipticArcRot
 
-void wxDCBase::Rotate( wxList* points, double angle, wxPoint center )
+void wxDCImpl::Rotate( wxPointList* points, double angle, wxPoint center )
 {
     if( angle != 0.0 )
     {
 {
     if( angle != 0.0 )
     {
-        double pi(3.1415926536);
+        double pi(M_PI);
         double dSinA = -sin(angle*2.0*pi/360.0);
         double dCosA = cos(angle*2.0*pi/360.0);
         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() )
+        wxPointList::compatibility_iterator node;
+        for ( node = points->GetFirst(); node; node = node->GetNext() )
         {
         {
-            wxPoint* point = (wxPoint*)node->Data();
-    
+            wxPoint* point = node->GetData();
+
             // transform coordinates, if necessary
             if( center.x ) point->x -= center.x;
             if( center.y ) point->y -= center.y;
             // transform coordinates, if necessary
             if( center.x ) point->x -= center.x;
             if( center.y ) point->y -= center.y;
@@ -736,12 +1449,12 @@ void wxDCBase::Rotate( wxList* points, double angle, wxPoint center )
     }
 }
 
     }
 }
 
-void wxDCBase::CalculateEllipticPoints( wxList* points, 
-                                        wxCoord xStart, wxCoord yStart, 
-                                        wxCoord w, wxCoord h, 
+void wxDCImpl::CalculateEllipticPoints( wxPointList* points,
+                                        wxCoord xStart, wxCoord yStart,
+                                        wxCoord w, wxCoord h,
                                         double sa, double ea )
 {
                                         double sa, double ea )
 {
-    double pi = 3.1415926535;
+    double pi = M_PI;
     double sar = 0;
     double ear = 0;
     int xsa = 0;
     double sar = 0;
     double ear = 0;
     int xsa = 0;
@@ -758,9 +1471,9 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
     wxCoord b = h/2;
     // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
     int decrX = 0;
     wxCoord b = h/2;
     // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
     int decrX = 0;
-    if( 2*a == w ) decrX = 1; 
+    if( 2*a == w ) decrX = 1;
     int decrY = 0;
     int decrY = 0;
-    if( 2*b == h ) decrY = 1; 
+    if( 2*b == h ) decrY = 1;
     // center
     wxCoord xCenter = xStart + a;
     wxCoord yCenter = yStart + b;
     // center
     wxCoord xCenter = xStart + a;
     wxCoord yCenter = yStart + b;
@@ -784,7 +1497,7 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
         ear = ea * pi / 180.0;
         // correct angle circle -> ellipse
         sar = atan( -a/(double)b * tan( sar ) );
         ear = ea * pi / 180.0;
         // correct angle circle -> ellipse
         sar = atan( -a/(double)b * tan( sar ) );
-        if ( sq == 1 || sq == 2 ) sar += pi; 
+        if ( sq == 1 || sq == 2 ) sar += pi;
         ear = atan( -a/(double)b * tan( ear ) );
         if ( eq == 1 || eq == 2 ) ear += pi;
         // coordinates of points
         ear = atan( -a/(double)b * tan( ear ) );
         if ( eq == 1 || eq == 2 ) ear += pi;
         // coordinates of points
@@ -809,7 +1522,7 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
     long y2_old = 0;
     long y_old = 0;
     // Lists for quadrant 1 to 4
     long y2_old = 0;
     long y_old = 0;
     // Lists for quadrant 1 to 4
-    wxList pointsarray[4];
+    wxPointList pointsarray[4];
     // Calculate points for first quadrant and set in all quadrants
     for( x = 0; x <= a; ++x )
     {
     // Calculate points for first quadrant and set in all quadrants
     for( x = 0; x <= a; ++x )
     {
@@ -823,47 +1536,48 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
             y2 = y2-y-y+1;
             --y;
         }
             y2 = y2-y-y+1;
             --y;
         }
-        // old y now to big: set point with old y, old x 
+        // old y now to big: set point with old y, old x
         if( bNewPoint && x>1)
         {
             int x1 = x - 1;
             // remove points on the same line
         if( bNewPoint && x>1)
         {
             int x1 = x - 1;
             // remove points on the same line
-            pointsarray[0].Insert( (wxObject*) new wxPoint( xCenter + x1 - decrX, yCenter - y_old ) );
-            pointsarray[1].Append( (wxObject*) new wxPoint( xCenter - x1, yCenter - y_old ) );
-            pointsarray[2].Insert( (wxObject*) new wxPoint( xCenter - x1, yCenter + y_old - decrY ) );
-            pointsarray[3].Append( (wxObject*) new wxPoint( xCenter + x1 - decrX, yCenter + y_old - decrY ) );
+            pointsarray[0].Insert( new wxPoint( xCenter + x1 - decrX, yCenter - y_old ) );
+            pointsarray[1].Append( new wxPoint( xCenter - x1, yCenter - y_old ) );
+            pointsarray[2].Insert( new wxPoint( xCenter - x1, yCenter + y_old - decrY ) );
+            pointsarray[3].Append( new wxPoint( xCenter + x1 - decrX, yCenter + y_old - decrY ) );
         } // set point
     } // calculate point
         } // set point
     } // calculate point
-    
+
     // Starting and/or ending points for the quadrants, first quadrant gets both.
     // Starting and/or ending points for the quadrants, first quadrant gets both.
-    pointsarray[0].Insert( (wxObject*) new wxPoint( xCenter + a - decrX, yCenter ) );
-    pointsarray[0].Append( (wxObject*) new wxPoint( xCenter, yCenter - b ) );
-    pointsarray[1].Append( (wxObject*) new wxPoint( xCenter - a, yCenter ) );
-    pointsarray[2].Append( (wxObject*) new wxPoint( xCenter, yCenter + b - decrY ) );
-    pointsarray[3].Append( (wxObject*) new wxPoint( xCenter + a - decrX, yCenter ) );
+    pointsarray[0].Insert( new wxPoint( xCenter + a - decrX, yCenter ) );
+    pointsarray[0].Append( new wxPoint( xCenter, yCenter - b ) );
+    pointsarray[1].Append( new wxPoint( xCenter - a, yCenter ) );
+    pointsarray[2].Append( new wxPoint( xCenter, yCenter + b - decrY ) );
+    pointsarray[3].Append( new wxPoint( xCenter + a - decrX, yCenter ) );
 
     // copy quadrants in original list
     if( bUseAngles )
     {
         // Copy the right part of the points in the lists
         // and delete the wxPoints, because they do not leave this method.
 
     // copy quadrants in original list
     if( bUseAngles )
     {
         // Copy the right part of the points in the lists
         // and delete the wxPoints, because they do not leave this method.
-        points->Append( (wxObject*) new wxPoint( xsa, ysa ) );
+        points->Append( new wxPoint( xsa, ysa ) );
         int q = sq;
         bool bStarted = false;
         bool bReady = false;
         bool bForceTurn = ( sq == eq && sa > ea );
         while( !bReady )
         {
         int q = sq;
         bool bStarted = false;
         bool bReady = false;
         bool bForceTurn = ( sq == eq && sa > ea );
         while( !bReady )
         {
-            for( wxNode *node = pointsarray[q].First(); node; node = node->Next() )
+            wxPointList::compatibility_iterator node;
+            for( 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->Data() )->x > xsa-1 && q >= 2
+                    (
+                      node->GetData()->x < xsa+1 && q <= 1
+                      ||
+                      node->GetData()->x > xsa-1 && q >= 2
                     )
                     )
-                  ) 
+                  )
                 {
                     bStarted = true;
                 }
                 {
                     bStarted = true;
                 }
@@ -873,18 +1587,18 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
                 {
                     if( q != eq || bForceTurn
                         ||
                 {
                     if( q != eq || bForceTurn
                         ||
-                        ( (wxPoint*) node->Data() )->x > xea+1 && q <= 1 
-                        ||  
-                        ( (wxPoint*) node->Data() )->x < xea-1 && q >= 2
+                        ( (wxPoint*) node->GetData() )->x > xea+1 && q <= 1
+                        ||
+                        ( (wxPoint*) node->GetData() )->x < xea-1 && q >= 2
                       )
                     {
                         // copy point
                       )
                     {
                         // copy point
-                        wxPoint* pPoint = new wxPoint( *((wxPoint*) node->Data() ) );
-                        points->Append( (wxObject*) pPoint );
+                        wxPoint* pPoint = new wxPoint( *(node->GetData()) );
+                        points->Append( pPoint );
                     }
                     }
-                    else if( q == eq && !bForceTurn || ( (wxPoint*) node->Data() )->x == xea)
+                    else if( q == eq && !bForceTurn || node->GetData()->x == xea)
                     {
                     {
-                        bReady = true; 
+                        bReady = true;
                     }
                 }
             } // for node
                     }
                 }
             } // for node
@@ -893,44 +1607,56 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
             bForceTurn = false;
             bStarted = true;
         } // while not bReady
             bForceTurn = false;
             bStarted = true;
         } // while not bReady
-        points->Append( (wxObject*) new wxPoint( xea, yea ) );
+        points->Append( new wxPoint( xea, yea ) );
 
         // 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() )
+            wxPointList::compatibility_iterator node;
+            for( node = pointsarray[q].GetFirst(); node; node = node->GetNext() )
             {
             {
-                wxPoint *p = (wxPoint *)node->Data();
+                wxPoint *p = node->GetData();
                 delete p;
             }
                 delete p;
             }
-        }            
-        
+        }
     }
     else
     {
     }
     else
     {
+        wxPointList::compatibility_iterator 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();
+            wxPoint *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();
+            wxPoint *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();
+            wxPoint *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();
+            wxPoint *p = node->GetData();
             points->Append( p );
         }
     } // not iUseAngles
 } // CalculateEllipticPoints
 
             points->Append( p );
         }
     } // not iUseAngles
 } // CalculateEllipticPoints
 
-#endif
+#endif // __WXWINCE__
 
 
+float wxDCImpl::GetFontPointSizeAdjustment(float dpi)
+{
+    // wxMSW has long-standing bug where wxFont point size is interpreted as
+    // "pixel size corresponding to given point size *on screen*". In other
+    // words, on a typical 600dpi printer and a typical 96dpi screen, fonts
+    // are ~6 times smaller when printing. Unfortunately, this bug is so severe
+    // that *all* printing code has to account for it and consequently, other
+    // ports need to emulate this bug too:
+    const wxSize screenPPI = wxGetDisplayPPI();
+    return float(screenPPI.y) / dpi;
+}