+#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
+
+#ifdef __WXMSW__
+ #include "wx/msw/dcclient.h"
+ #include "wx/msw/dcmemory.h"
+ #include "wx/msw/dcscreen.h"
+#endif
+
+#ifdef __WXGTK__
+ #include "wx/gtk/dcclient.h"
+ #include "wx/gtk/dcmemory.h"
+ #include "wx/gtk/dcscreen.h"
+#endif
+
+#ifdef __WXMAC__
+ #include "wx/mac/dcclient.h"
+ #include "wx/mac/dcmemory.h"
+ #include "wx/mac/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 )
+{
+ return new wxWindowDCImpl( owner );
+}
+
+wxDCImpl* wxNativeDCFactory::CreateWindowDC( wxWindowDC *owner, wxWindow *window )
+{
+ return new wxWindowDCImpl( owner, window );
+}
+
+wxDCImpl* wxNativeDCFactory::CreateClientDC( wxClientDC *owner )
+{
+ return new wxClientDCImpl( owner );
+}
+
+wxDCImpl* wxNativeDCFactory::CreateClientDC( wxClientDC *owner, wxWindow *window )
+{
+ return new wxClientDCImpl( owner, window );
+}
+
+wxDCImpl* wxNativeDCFactory::CreatePaintDC( wxPaintDC *owner )
+{
+ return new wxPaintDCImpl( owner );
+}
+
+wxDCImpl* wxNativeDCFactory::CreatePaintDC( wxPaintDC *owner, wxWindow *window )
+{
+ return new wxPaintDCImpl( owner, window );
+}
+
+wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner )
+{
+ return new wxMemoryDCImpl( owner );
+}
+
+wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner, wxBitmap &bitmap )
+{
+ 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()
+{
+ return GetImpl()->GetPaperRect();
+}
+
+int wxPrinterDC::GetResolution()
+{
+ 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(wxTRANSPARENT)
+ , m_mappingMode(wxMM_TEXT)
+ , m_pen()
+ , m_brush()
+ , m_backgroundBrush(*wxTRANSPARENT_BRUSH)
+ , 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()
+{
+}
+
+// ----------------------------------------------------------------------------
+// coordinate conversions and transforms
+// ----------------------------------------------------------------------------
+
+wxCoord wxDCImpl::DeviceToLogicalX(wxCoord x) const
+{
+ return wxRound((double)(x - m_deviceOriginX - m_deviceLocalOriginX) / m_scaleX) * m_signX + m_logicalOriginX;
+}
+
+wxCoord wxDCImpl::DeviceToLogicalY(wxCoord y) const
+{
+ return wxRound((double)(y - m_deviceOriginY - m_deviceLocalOriginY) / m_scaleY) * m_signY + 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_scaleX) * m_signX + m_deviceOriginX * m_signY + m_deviceLocalOriginX;
+}
+
+wxCoord wxDCImpl::LogicalToDeviceY(wxCoord y) const
+{
+ return wxRound((double)(y - m_logicalOriginY) * m_scaleY) * m_signY + m_deviceOriginY * m_signY + 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;