]> git.saurik.com Git - wxWidgets.git/commitdiff
Add support for GTK print, modified from patch 1782055
authorRobert Roebling <robert@roebling.de>
Wed, 5 Sep 2007 21:34:08 +0000 (21:34 +0000)
committerRobert Roebling <robert@roebling.de>
Wed, 5 Sep 2007 21:34:08 +0000 (21:34 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48578 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

Makefile.in
build/bakefiles/files.bkl
include/wx/gtk/print.h [new file with mode: 0644]
src/generic/prntdlgg.cpp
src/gtk/print.cpp [new file with mode: 0644]

index 16db1b61524172508ee55749e6404b3abf4f36c3..c249f0ce67e6c7dbc041d674c6a4fd43bda69d75 100644 (file)
@@ -2344,6 +2344,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_GUI_HDR =  \
        wx/gtk/gauge.h \
        wx/gtk/gnome/gprint.h \
        wx/gtk/gnome/gvfs.h \
+       wx/gtk/print.h \
        wx/gtk/listbox.h \
        wx/gtk/mdi.h \
        wx/gtk/menu.h \
@@ -4534,6 +4535,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___GUI_SRC_OBJECTS =  \
        monodll_gauge.o \
        monodll_gprint.o \
        monodll_gvfs.o \
+       monodll_print.o \
        monodll_listbox.o \
        monodll_mdi.o \
        monodll_menu.o \
@@ -6380,6 +6382,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___GUI_SRC_OBJECTS_1 =  \
        monolib_gauge.o \
        monolib_gprint.o \
        monolib_gvfs.o \
+       monolib_print.o \
        monolib_listbox.o \
        monolib_mdi.o \
        monolib_menu.o \
@@ -8500,6 +8503,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___GUI_SRC_OBJECTS_2 =  \
        coredll_gauge.o \
        coredll_gprint.o \
        coredll_gvfs.o \
+       coredll_print.o \
        coredll_listbox.o \
        coredll_mdi.o \
        coredll_menu.o \
@@ -9956,6 +9960,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___GUI_SRC_OBJECTS_3 =  \
        corelib_gauge.o \
        corelib_gprint.o \
        corelib_gvfs.o \
+       corelib_print.o \
        corelib_listbox.o \
        corelib_mdi.o \
        corelib_menu.o \
@@ -13961,9 +13966,6 @@ monodll_regiong.o: $(srcdir)/src/generic/regiong.cpp $(MONODLL_ODEP)
 monodll_gsockpm.o: $(srcdir)/src/os2/gsockpm.cpp $(MONODLL_ODEP)
        $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/os2/gsockpm.cpp
 
-monodll_print.o: $(srcdir)/src/os2/print.cpp $(MONODLL_ODEP)
-       $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/os2/print.cpp
-
 monodll_colschem.o: $(srcdir)/src/univ/colschem.cpp $(MONODLL_ODEP)
        $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/univ/colschem.cpp
 
@@ -16589,6 +16591,12 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP)
 @COND_USE_GUI_1_WXUNIV_1@monodll_gauge.o: $(srcdir)/src/univ/gauge.cpp $(MONODLL_ODEP)
 @COND_USE_GUI_1_WXUNIV_1@      $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/univ/gauge.cpp
 
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@monodll_print.o: $(srcdir)/src/gtk/print.cpp $(MONODLL_ODEP)
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@        $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/print.cpp
+
+@COND_TOOLKIT_PM_USE_GUI_1_WXUNIV_0@monodll_print.o: $(srcdir)/src/os2/print.cpp $(MONODLL_ODEP)
+@COND_TOOLKIT_PM_USE_GUI_1_WXUNIV_0@   $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/os2/print.cpp
+
 @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@monodll_listbox.o: $(srcdir)/src/gtk/listbox.cpp $(MONODLL_ODEP)
 @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@        $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/listbox.cpp
 
@@ -18293,9 +18301,6 @@ monolib_regiong.o: $(srcdir)/src/generic/regiong.cpp $(MONOLIB_ODEP)
 monolib_gsockpm.o: $(srcdir)/src/os2/gsockpm.cpp $(MONOLIB_ODEP)
        $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/os2/gsockpm.cpp
 
-monolib_print.o: $(srcdir)/src/os2/print.cpp $(MONOLIB_ODEP)
-       $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/os2/print.cpp
-
 monolib_colschem.o: $(srcdir)/src/univ/colschem.cpp $(MONOLIB_ODEP)
        $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/univ/colschem.cpp
 
@@ -20921,6 +20926,12 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP)
 @COND_USE_GUI_1_WXUNIV_1@monolib_gauge.o: $(srcdir)/src/univ/gauge.cpp $(MONOLIB_ODEP)
 @COND_USE_GUI_1_WXUNIV_1@      $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/univ/gauge.cpp
 
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@monolib_print.o: $(srcdir)/src/gtk/print.cpp $(MONOLIB_ODEP)
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@        $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/print.cpp
+
+@COND_TOOLKIT_PM_USE_GUI_1_WXUNIV_0@monolib_print.o: $(srcdir)/src/os2/print.cpp $(MONOLIB_ODEP)
+@COND_TOOLKIT_PM_USE_GUI_1_WXUNIV_0@   $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/os2/print.cpp
+
 @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@monolib_listbox.o: $(srcdir)/src/gtk/listbox.cpp $(MONOLIB_ODEP)
 @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@        $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/listbox.cpp
 
@@ -23960,9 +23971,6 @@ coredll_regiong.o: $(srcdir)/src/generic/regiong.cpp $(COREDLL_ODEP)
 coredll_gsockpm.o: $(srcdir)/src/os2/gsockpm.cpp $(COREDLL_ODEP)
        $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/os2/gsockpm.cpp
 
-coredll_print.o: $(srcdir)/src/os2/print.cpp $(COREDLL_ODEP)
-       $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/os2/print.cpp
-
 coredll_colschem.o: $(srcdir)/src/univ/colschem.cpp $(COREDLL_ODEP)
        $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/univ/colschem.cpp
 
@@ -25799,6 +25807,12 @@ coredll_win32.o: $(srcdir)/src/univ/themes/win32.cpp $(COREDLL_ODEP)
 @COND_USE_GUI_1_WXUNIV_1@coredll_gauge.o: $(srcdir)/src/univ/gauge.cpp $(COREDLL_ODEP)
 @COND_USE_GUI_1_WXUNIV_1@      $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/univ/gauge.cpp
 
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@coredll_print.o: $(srcdir)/src/gtk/print.cpp $(COREDLL_ODEP)
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@        $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/print.cpp
+
+@COND_TOOLKIT_PM_USE_GUI_1_WXUNIV_0@coredll_print.o: $(srcdir)/src/os2/print.cpp $(COREDLL_ODEP)
+@COND_TOOLKIT_PM_USE_GUI_1_WXUNIV_0@   $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/os2/print.cpp
+
 @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@coredll_listbox.o: $(srcdir)/src/gtk/listbox.cpp $(COREDLL_ODEP)
 @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@        $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/listbox.cpp
 
@@ -26918,9 +26932,6 @@ corelib_regiong.o: $(srcdir)/src/generic/regiong.cpp $(CORELIB_ODEP)
 corelib_gsockpm.o: $(srcdir)/src/os2/gsockpm.cpp $(CORELIB_ODEP)
        $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/os2/gsockpm.cpp
 
-corelib_print.o: $(srcdir)/src/os2/print.cpp $(CORELIB_ODEP)
-       $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/os2/print.cpp
-
 corelib_colschem.o: $(srcdir)/src/univ/colschem.cpp $(CORELIB_ODEP)
        $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/univ/colschem.cpp
 
@@ -28757,6 +28768,12 @@ corelib_win32.o: $(srcdir)/src/univ/themes/win32.cpp $(CORELIB_ODEP)
 @COND_USE_GUI_1_WXUNIV_1@corelib_gauge.o: $(srcdir)/src/univ/gauge.cpp $(CORELIB_ODEP)
 @COND_USE_GUI_1_WXUNIV_1@      $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/univ/gauge.cpp
 
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@corelib_print.o: $(srcdir)/src/gtk/print.cpp $(CORELIB_ODEP)
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@        $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/print.cpp
+
+@COND_TOOLKIT_PM_USE_GUI_1_WXUNIV_0@corelib_print.o: $(srcdir)/src/os2/print.cpp $(CORELIB_ODEP)
+@COND_TOOLKIT_PM_USE_GUI_1_WXUNIV_0@   $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/os2/print.cpp
+
 @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@corelib_listbox.o: $(srcdir)/src/gtk/listbox.cpp $(CORELIB_ODEP)
 @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1_WXUNIV_0@        $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/listbox.cpp
 
index 2b48015a984341ed8017623b27681c847089d5fd..8325476eff78ac8a565e857e6000ef9499e0743e 100644 (file)
@@ -1056,6 +1056,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
     src/gtk/gauge.cpp
     src/gtk/gnome/gprint.cpp
     src/gtk/gnome/gvfs.cpp
+    src/gtk/print.cpp
     src/gtk/listbox.cpp
     src/gtk/mdi.cpp
     src/gtk/menu.cpp
@@ -1106,6 +1107,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
     wx/gtk/gauge.h
     wx/gtk/gnome/gprint.h
     wx/gtk/gnome/gvfs.h
+    wx/gtk/print.h
     wx/gtk/listbox.h
     wx/gtk/mdi.h
     wx/gtk/menu.h
diff --git a/include/wx/gtk/print.h b/include/wx/gtk/print.h
new file mode 100644 (file)
index 0000000..ae98de2
--- /dev/null
@@ -0,0 +1,400 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/gtk/print.h
+// Author:      Anthony Bretaudeau
+// Purpose:     GTK printing support
+// Created:     2007-08-25
+// RCS-ID:      $Id: print.h,v 1 2007-08-25 05:44:44 PC Exp $
+// Copyright:   (c) 2007 wxWidgets development team
+// Licence:     wxWindows Licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_GTK_PRINT_H_
+#define _WX_GTK_PRINT_H_
+
+#include "wx/defs.h"
+
+#if wxUSE_GTKPRINT
+
+#include "wx/print.h"
+#include "wx/printdlg.h"
+#include "wx/prntbase.h"
+#include "wx/dc.h"
+
+typedef struct _GtkPrintOperation GtkPrintOperation;
+typedef struct _GtkPrintContext GtkPrintContext;
+typedef struct _GtkPrintSettings GtkPrintSettings;
+typedef struct _GtkPageSetup GtkPageSetup;
+
+typedef struct _cairo cairo_t;
+
+//----------------------------------------------------------------------------
+// wxGtkPrintFactory
+//----------------------------------------------------------------------------
+
+class wxGtkPrintFactory: public wxPrintFactory
+{
+public:
+    virtual wxPrinterBase *CreatePrinter( wxPrintDialogData *data );
+
+    virtual wxPrintPreviewBase *CreatePrintPreview( wxPrintout *preview,
+                                                    wxPrintout *printout = NULL,
+                                                    wxPrintDialogData *data = NULL );
+    virtual wxPrintPreviewBase *CreatePrintPreview( wxPrintout *preview,
+                                                    wxPrintout *printout,
+                                                    wxPrintData *data );
+
+    virtual wxPrintDialogBase *CreatePrintDialog( wxWindow *parent,
+                                                  wxPrintDialogData *data = NULL );
+    virtual wxPrintDialogBase *CreatePrintDialog( wxWindow *parent,
+                                                  wxPrintData *data );
+
+    virtual wxPageSetupDialogBase *CreatePageSetupDialog( wxWindow *parent,
+                                                          wxPageSetupDialogData * data = NULL );
+
+    virtual wxDC* CreatePrinterDC( const wxPrintData& data );
+
+    virtual bool HasPrintSetupDialog();
+    virtual wxDialog *CreatePrintSetupDialog( wxWindow *parent, wxPrintData *data );
+    virtual bool HasOwnPrintToFile();
+    virtual bool HasPrinterLine();
+    virtual wxString CreatePrinterLine();
+    virtual bool HasStatusLine();
+    virtual wxString CreateStatusLine();
+
+    virtual wxPrintNativeDataBase *CreatePrintNativeData();
+};
+
+//----------------------------------------------------------------------------
+// wxGtkPrintDialog
+//----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxGtkPrintDialog: public wxPrintDialogBase
+{
+public:
+    wxGtkPrintDialog( wxWindow *parent,
+                         wxPrintDialogData* data = NULL );
+    wxGtkPrintDialog( wxWindow *parent, wxPrintData* data);
+    virtual ~wxGtkPrintDialog();
+
+    wxPrintData& GetPrintData()
+        { return m_printDialogData.GetPrintData(); }
+    wxPrintDialogData& GetPrintDialogData()
+        { return m_printDialogData; }
+
+    wxDC *GetPrintDC() { return m_dc; }
+    void SetPrintDC(wxDC * printDC) { m_dc = printDC; }
+
+    virtual int ShowModal();
+
+    virtual bool Validate() { return true; }
+    virtual bool TransferDataToWindow() { return true; }
+    virtual bool TransferDataFromWindow() { return true; }
+
+    void SetShowDialog(bool show) { m_showDialog = show; }
+    bool GetShowDialog() { return m_showDialog; }
+
+protected:
+    // Implement some base class methods to do nothing to avoid asserts and
+    // GTK warnings, since this is not a real wxDialog.
+    virtual void DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
+                           int WXUNUSED(width), int WXUNUSED(height),
+                           int WXUNUSED(sizeFlags) = wxSIZE_AUTO) {}
+    virtual void DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y),
+                              int WXUNUSED(width), int WXUNUSED(height)) {}
+
+private:
+    wxPrintDialogData    m_printDialogData;
+    wxWindow            *m_parent;
+    bool                 m_showDialog;
+    wxDC                *m_dc;
+
+    DECLARE_DYNAMIC_CLASS(wxGtkPrintDialog)
+};
+
+//----------------------------------------------------------------------------
+// wxGtkPageSetupDialog
+//----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxGtkPageSetupDialog: public wxPageSetupDialogBase
+{
+public:
+    wxGtkPageSetupDialog( wxWindow *parent,
+                            wxPageSetupDialogData* data = NULL );
+    virtual ~wxGtkPageSetupDialog();
+
+    virtual wxPageSetupDialogData& GetPageSetupDialogData() { return m_pageDialogData; }
+
+    virtual int ShowModal();
+
+    virtual bool Validate() { return true; }
+    virtual bool TransferDataToWindow() { return true; }
+    virtual bool TransferDataFromWindow() { return true; }
+
+protected:
+    // Implement some base class methods to do nothing to avoid asserts and
+    // GTK warnings, since this is not a real wxDialog.
+    virtual void DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
+                           int WXUNUSED(width), int WXUNUSED(height),
+                           int WXUNUSED(sizeFlags) = wxSIZE_AUTO) {}
+    virtual void DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y),
+                              int WXUNUSED(width), int WXUNUSED(height)) {}
+
+private:
+    wxPageSetupDialogData    m_pageDialogData;
+    wxWindow                *m_parent;
+
+    DECLARE_DYNAMIC_CLASS(wxGtkPageSetupDialog)
+};
+
+//----------------------------------------------------------------------------
+// wxGtkPrinter
+//----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxGtkPrinter : public wxPrinterBase
+{
+public:
+    wxGtkPrinter(wxPrintDialogData *data = NULL);
+    virtual ~wxGtkPrinter();
+
+    virtual bool Print(wxWindow *parent,
+                       wxPrintout *printout,
+                       bool prompt = true);
+    virtual wxDC* PrintDialog(wxWindow *parent);
+    virtual bool Setup(wxWindow *parent);
+
+    GtkPrintContext *GetPrintContext() { return m_gpc; }
+    void SetPrintContext(GtkPrintContext *context) {m_gpc = context;}
+    void BeginPrint(wxPrintout *printout, GtkPrintOperation *operation, GtkPrintContext *context);
+    void DrawPage(wxPrintout *printout, GtkPrintOperation *operation, GtkPrintContext *context, int page_nr);
+
+private:
+    GtkPrintContext *m_gpc;
+    bool             m_showDialog;
+    wxDC            *m_dc;
+
+    DECLARE_DYNAMIC_CLASS(wxGtkPrinter)
+    DECLARE_NO_COPY_CLASS(wxGtkPrinter)
+};
+
+//----------------------------------------------------------------------------
+// wxGtkPrintNativeData
+//----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxGtkPrintNativeData : public wxPrintNativeDataBase
+{
+public:
+    wxGtkPrintNativeData();
+    virtual ~wxGtkPrintNativeData();
+
+    virtual bool TransferTo( wxPrintData &data );
+    virtual bool TransferFrom( const wxPrintData &data );
+
+    virtual bool Ok() const { return IsOk(); }
+    virtual bool IsOk() const { return true; }
+
+    GtkPrintSettings* GetPrintConfig() { return m_config; }
+    void SetPrintConfig( GtkPrintSettings * config );
+
+    void SetPrintJob( GtkPrintOperation *job ) { m_job = job; }
+    GtkPrintOperation* GetPrintJob() { return m_job; }
+
+    GtkPrintContext *GetPrintContext() { return m_context; }
+    void SetPrintContext(GtkPrintContext *context) {m_context = context; }
+
+
+    GtkPageSetup* GetPageSetupFromSettings(GtkPrintSettings* settings);
+    void SetPageSetupToSettings(GtkPrintSettings* settings, GtkPageSetup* page_setup);
+
+private:
+    GtkPrintSettings    *m_config;
+    GtkPrintOperation   *m_job;
+    GtkPrintContext     *m_context;
+
+    DECLARE_DYNAMIC_CLASS(wxGtkPrintNativeData)
+};
+
+//-----------------------------------------------------------------------------
+// wxGtkPrintDC
+//-----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxGtkPrintDC: public wxDC
+{
+public:
+    wxGtkPrintDC( const wxPrintData& data );
+    virtual ~wxGtkPrintDC();
+
+    bool Ok() const { return IsOk(); }
+    bool IsOk() const;
+
+    bool CanDrawBitmap() const { return true; }
+    void Clear();
+    void SetFont( const wxFont& font );
+    void SetPen( const wxPen& pen );
+    void SetBrush( const wxBrush& brush );
+    void SetLogicalFunction( int function );
+    void SetBackground( const wxBrush& brush );
+    void DestroyClippingRegion();
+    bool StartDoc(const wxString& message);
+    void EndDoc();
+    void StartPage();
+    void EndPage();
+    wxCoord GetCharHeight() const;
+    wxCoord GetCharWidth() const;
+    bool CanGetTextExtent() const { return true; }
+    wxSize GetPPI() const;
+    void SetLogicalOrigin( wxCoord x, wxCoord y );
+    void SetDeviceOrigin( wxCoord x, wxCoord y );
+    virtual int GetDepth() const { return 24; }
+    void SetBackgroundMode(int WXUNUSED(mode));
+    void SetPalette(const wxPalette& WXUNUSED(palette)) { }
+    static void SetResolution(int ppi);
+    static int GetResolution();
+    void DrawScaledBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, wxCoord w, wxCoord h,
+                    bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL)
+        { DoDrawScaledBitmap( bmp, x, y, w, h, useMask, quality ); }
+    void DrawScaledBitmap(const wxBitmap &bmp, const wxPoint& pt, const wxSize& sz,
+                    bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL)
+        { DoDrawScaledBitmap( bmp, pt.x, pt.y, sz.x, sz.y, useMask, quality ); }
+    void DrawScaledBitmap(const wxBitmap &bmp, const wxRect& rect,
+                    bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL)
+        { DoDrawScaledBitmap( bmp, rect.x, rect.y, rect.width, rect.height, useMask, quality ); }
+
+protected:
+    bool DoFloodFill(wxCoord x1, wxCoord y1, const wxColour &col, int style=wxFLOOD_SURFACE );
+    void DoGradientFillConcentric(const wxRect& rect, const wxColour& initialColour, const wxColour& destColour, const wxPoint& circleCenter);
+    void DoGradientFillLinear(const wxRect& rect, const wxColour& initialColour, const wxColour& destColour, wxDirection nDirection = wxEAST);
+    bool DoGetPixel(wxCoord x1, wxCoord y1, wxColour *col) const;
+    void DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2);
+    void DoCrossHair(wxCoord x, wxCoord y);
+    void DoDrawArc(wxCoord x1,wxCoord y1,wxCoord x2,wxCoord y2,wxCoord xc,wxCoord yc);
+    void DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea);
+    void DoDrawPoint(wxCoord x, wxCoord y);
+    void DoDrawLines(int n, wxPoint points[], wxCoord xoffset = 0, wxCoord yoffset = 0);
+    void DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset = 0, wxCoord yoffset = 0, int fillStyle=wxODDEVEN_RULE);
+    void DoDrawPolyPolygon(int n, int count[], wxPoint points[], wxCoord xoffset = 0, wxCoord yoffset = 0, int fillStyle=wxODDEVEN_RULE);
+    void DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height);
+    void DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius = 20.0);
+    void DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height);
+#if wxUSE_SPLINES
+    void DoDrawSpline(wxList *points);
+#endif // wxUSE_SPLINES
+    bool DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
+            wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop = wxCOPY, bool useMask = false,
+            wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord);
+    void DoDrawIcon( const wxIcon& icon, wxCoord x, wxCoord y );
+    void DoDrawBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y, bool useMask = false  );
+    void DoDrawScaledBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y, wxCoord w, wxCoord h, bool useMask = false, int quality = wxIMAGE_QUALITY_NORMAL );
+    void DoDrawText(const wxString& text, wxCoord x, wxCoord y );
+    void DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle);
+    void DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord width, wxCoord height);
+    void DoSetClippingRegionAsRegion( const wxRegion &WXUNUSED(clip) ) { }
+    void DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y,
+                     wxCoord *descent = (wxCoord *) NULL,
+                     wxCoord *externalLeading = (wxCoord *) NULL,
+                     const wxFont *theFont = (wxFont *) NULL ) const;
+    void DoGetSize(int* width, int* height) const;
+    void DoGetSizeMM(int *width, int *height) const;
+
+    wxPrintData& GetPrintData() { return m_printData; }
+    void SetPrintData(const wxPrintData& data);
+
+    void ComputeScaleAndOrigin();
+
+private:
+    static float ms_PSScaleFactor;
+
+    wxPrintData             m_printData;
+    PangoContext           *m_context;
+    PangoLayout            *m_layout;
+    PangoFontDescription   *m_fontdesc;
+    cairo_t                *m_cairo;
+
+    unsigned char           m_currentRed;
+    unsigned char           m_currentGreen;
+    unsigned char           m_currentBlue;
+    unsigned char           m_currentAlpha;
+
+    int                     m_deviceOffsetY;
+    int                     m_deviceOffsetX;
+
+    GtkPrintContext      *m_gpc;
+    static int            ms_resolution;
+
+    wxCoord DeviceToLogicalX(wxCoord x) const
+    {
+        int addValue = 0;
+        if (m_signX == -1) addValue = m_deviceOffsetX - m_deviceOriginX; // right to left
+        else addValue = m_deviceOriginX;// left to right
+        return (wxCoord) ((double)(x - addValue) * m_signX + m_logicalOriginX);
+    }
+    wxCoord DeviceToLogicalXRel(wxCoord x) const
+    {
+        return x;
+    }
+    wxCoord DeviceToLogicalY(wxCoord y) const
+    {
+        int addValue = 0;
+        if (m_signY == -1) addValue = m_deviceOffsetY - m_deviceOriginY; // bottom to up
+        else addValue = m_deviceOriginY;// up to bottom
+        return (wxCoord) ((double)(y - addValue) * m_signY + m_logicalOriginY);
+    }
+    wxCoord DeviceToLogicalYRel(wxCoord y) const
+    {
+        return y;
+    }
+    wxCoord LogicalToDeviceX(wxCoord x) const
+    {
+        int addValue = 0;
+        if (m_signX == -1) addValue = m_deviceOffsetX - m_deviceOriginX; // right to left
+        else addValue = m_deviceOriginX;// left to right
+        return (wxCoord) ((double)(x - m_logicalOriginX) * m_signX + addValue);
+    }
+    wxCoord LogicalToDeviceXRel(wxCoord x) const
+    {
+        return x;
+    }
+    wxCoord LogicalToDeviceY(wxCoord y) const
+    {
+        int addValue = 0;
+        if (m_signY == -1) addValue = m_deviceOffsetY - m_deviceOriginY; // bottom to up
+        else addValue = m_deviceOriginY;// up to bottom
+        return (wxCoord) ((double)(y - m_logicalOriginY)  * m_signY + addValue);
+    }
+    wxCoord LogicalToDeviceYRel(wxCoord y) const
+    {
+        return y;
+    }
+
+    DECLARE_DYNAMIC_CLASS(wxGtkPrintDC)
+    DECLARE_NO_COPY_CLASS(wxGtkPrintDC)
+};
+
+// ----------------------------------------------------------------------------
+// wxGtkPrintPreview: programmer creates an object of this class to preview a
+// wxPrintout.
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxGtkPrintPreview : public wxPrintPreviewBase
+{
+public:
+    wxGtkPrintPreview(wxPrintout *printout,
+                             wxPrintout *printoutForPrinting = (wxPrintout *) NULL,
+                             wxPrintDialogData *data = (wxPrintDialogData *) NULL);
+    wxGtkPrintPreview(wxPrintout *printout,
+                             wxPrintout *printoutForPrinting,
+                             wxPrintData *data);
+
+    virtual ~wxGtkPrintPreview();
+
+    virtual bool Print(bool interactive);
+    virtual void DetermineScaling();
+
+private:
+    void Init(wxPrintout *printout, wxPrintout *printoutForPrinting);
+
+    DECLARE_CLASS(wxGtkPrintPreview)
+};
+
+#endif
+
+#endif
index 110cb87ea399fd584a286248f641edb0ee07e1ee..02f143493733e176755e3c7211ea679508352fe0 100644 (file)
@@ -68,8 +68,8 @@
 #endif
 
 #if wxUSE_GTKPRINT
-    // #include "wx/link.h"
-    // wxFORCE_LINK_MODULE(gtk_print)
+    #include "wx/link.h"
+    wxFORCE_LINK_MODULE(gtk_print)
 #endif
 
 // ----------------------------------------------------------------------------
diff --git a/src/gtk/print.cpp b/src/gtk/print.cpp
new file mode 100644 (file)
index 0000000..d3c20a3
--- /dev/null
@@ -0,0 +1,2414 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/gtk/print.cpp
+// Author:      Anthony Bretaudeau
+// Purpose:     GTK printing support
+// Created:     2007-08-25
+// RCS-ID:      $Id: print.cpp,v 1 2007-08-25 05:44:44 PC Exp $
+// Copyright:   (c) 2007 wxWidgets development team
+// Licence:     wxWindows Licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#if wxUSE_GTKPRINT
+
+#include "wx/gtk/print.h"
+
+#ifndef WX_PRECOMP
+#include "wx/log.h"
+#include "wx/dcmemory.h"
+#include "wx/icon.h"
+#include "wx/math.h"
+#include "wx/image.h"
+#include "wx/module.h"
+#endif
+
+#include "wx/fontutil.h"
+#include "wx/gtk/private.h"
+#include "wx/dynlib.h"
+#include "wx/paper.h"
+#include "wx/rawbmp.h"
+
+#include <gtk/gtk.h>
+#include <gtk/gtkpagesetupunixdialog.h>
+
+#include "wx/link.h"
+wxFORCE_LINK_THIS_MODULE(gtk_print)
+
+#if wxUSE_LIBGNOMEPRINT
+#include "wx/gtk/gnome/gprint.h"
+#endif
+
+// Usefull to convert angles from/to Rad to/from Deg.
+static const double RAD2DEG  = 180.0 / M_PI;
+static const double DEG2RAD  = M_PI / 180.0;
+
+//----------------------------------------------------------------------------
+// wxGtkPrintModule
+// Initialized when starting the app : if it successfully load the gtk-print framework,
+// it uses it. If not, it falls back to gnome print (see /gtk/gnome/gprint.cpp) then
+// to postscript if gnomeprint is not available.
+//----------------------------------------------------------------------------
+
+class wxGtkPrintModule: public wxModule
+{
+public:
+    wxGtkPrintModule() 
+    {
+#if wxUSE_LIBGNOMEPRINT
+        // This module must be initialized AFTER gnomeprint's one
+        AddDependency(CLASSINFO(wxGnomePrintModule));
+#endif
+    }
+    bool OnInit();
+    void OnExit();
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxGtkPrintModule)
+};
+
+bool wxGtkPrintModule::OnInit()
+{
+    if (gtk_check_version(2,10,0) == NULL)
+        wxPrintFactory::SetPrintFactory( new wxGtkPrintFactory );
+        
+    return true;
+}
+
+void wxGtkPrintModule::OnExit()
+{
+}
+
+IMPLEMENT_DYNAMIC_CLASS(wxGtkPrintModule, wxModule)
+
+
+//----------------------------------------------------------------------------
+// wxGtkPrintFactory
+//----------------------------------------------------------------------------
+
+wxPrinterBase* wxGtkPrintFactory::CreatePrinter( wxPrintDialogData *data )
+{
+    return new wxGtkPrinter( data );
+}
+
+wxPrintPreviewBase *wxGtkPrintFactory::CreatePrintPreview( wxPrintout *preview,
+                                                    wxPrintout *printout,
+                                                    wxPrintDialogData *data )
+{
+    return new wxGtkPrintPreview( preview, printout, data );
+}
+
+wxPrintPreviewBase *wxGtkPrintFactory::CreatePrintPreview( wxPrintout *preview,
+                                                    wxPrintout *printout,
+                                                    wxPrintData *data )
+{
+    return new wxGtkPrintPreview( preview, printout, data );
+}
+
+wxPrintDialogBase *wxGtkPrintFactory::CreatePrintDialog( wxWindow *parent,
+                                                  wxPrintDialogData *data )
+{
+    return new wxGtkPrintDialog( parent, data );
+}
+
+wxPrintDialogBase *wxGtkPrintFactory::CreatePrintDialog( wxWindow *parent,
+                                                  wxPrintData *data )
+{
+    return new wxGtkPrintDialog( parent, data );
+}
+
+wxPageSetupDialogBase *wxGtkPrintFactory::CreatePageSetupDialog( wxWindow *parent,
+                                                          wxPageSetupDialogData * data )
+{
+    return new wxGtkPageSetupDialog( parent, data );
+}
+
+bool wxGtkPrintFactory::HasPrintSetupDialog()
+{
+    return false;
+}
+
+wxDialog *wxGtkPrintFactory::CreatePrintSetupDialog( wxWindow *parent, wxPrintData *data )
+{
+    return NULL;
+}
+
+wxDC* wxGtkPrintFactory::CreatePrinterDC( const wxPrintData& data )
+{
+    return new wxGtkPrintDC(data);
+}
+
+bool wxGtkPrintFactory::HasOwnPrintToFile()
+{
+    return true;
+}
+
+bool wxGtkPrintFactory::HasPrinterLine()
+{
+    return true;
+}
+
+wxString wxGtkPrintFactory::CreatePrinterLine()
+{
+    // redundant now
+    return wxEmptyString;
+}
+
+bool wxGtkPrintFactory::HasStatusLine()
+{
+    // redundant now
+    return true;
+}
+
+wxString wxGtkPrintFactory::CreateStatusLine()
+{
+    // redundant now
+    return wxEmptyString;
+}
+
+wxPrintNativeDataBase *wxGtkPrintFactory::CreatePrintNativeData()
+{
+    return new wxGtkPrintNativeData;
+}
+
+//----------------------------------------------------------------------------
+// Callback functions for Gtk Printings.
+//----------------------------------------------------------------------------
+
+// We use it to pass useful objets to gtk printing callback functions.
+typedef struct
+{
+   wxGtkPrinter * printer;
+   wxPrintout * printout;
+}
+wxPrinterToGtkData;
+
+extern "C"
+{
+    static void gtk_begin_print_callback (GtkPrintOperation *operation, GtkPrintContext *context, gpointer user_data)
+    {
+        wxPrinterToGtkData *data = (wxPrinterToGtkData *) user_data;
+
+        data->printer->BeginPrint(data->printout, operation, context);
+    }
+
+    static void gtk_draw_page_print_callback (GtkPrintOperation *operation, GtkPrintContext *context, gint page_nr, gpointer user_data)
+    {
+        wxPrinterToGtkData *data = (wxPrinterToGtkData *) user_data;
+
+        data->printer->DrawPage(data->printout, operation, context, page_nr);
+    }
+
+    static void gtk_end_print_callback (GtkPrintOperation *operation, GtkPrintContext *context, gpointer user_data)
+    {
+        wxPrintout *printout = (wxPrintout *) user_data;
+
+        printout->OnEndPrinting();
+    }
+
+    static gboolean gtk_preview_print_callback (GtkPrintOperation *operation, GtkPrintOperationPreview *preview, GtkPrintContext *context, GtkWindow *parent, gpointer user_data)
+    {
+        wxPrintout *printout = (wxPrintout *) user_data;
+
+        printout->SetIsPreview(true);
+
+        /* We create a cairo context with 72dpi resolution. This resolution is only used for positionning. */
+        cairo_t *cairo = gdk_cairo_create(GTK_WIDGET(parent)->window);
+        gtk_print_context_set_cairo_context(context, cairo, 72, 72);
+
+        return false;
+    }
+}
+
+//----------------------------------------------------------------------------
+// wxGtkPrintNativeData
+//----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGtkPrintNativeData, wxPrintNativeDataBase)
+
+wxGtkPrintNativeData::wxGtkPrintNativeData()
+{
+    m_config = gtk_print_settings_new();
+}
+
+wxGtkPrintNativeData::~wxGtkPrintNativeData()
+{
+    g_object_unref (m_config);
+}
+
+// Convert datas stored in m_config to a wxPrintData.
+// Called by wxPrintData::ConvertFromNative().
+bool wxGtkPrintNativeData::TransferTo( wxPrintData &data )
+{
+    if(!m_config)
+        return false;
+
+    GtkPrintQuality quality = gtk_print_settings_get_quality(m_config);
+    if (quality == GTK_PRINT_QUALITY_HIGH)
+        data.SetQuality(wxPRINT_QUALITY_HIGH);
+    else if (quality == GTK_PRINT_QUALITY_LOW)
+        data.SetQuality(wxPRINT_QUALITY_LOW);
+    else if (quality == GTK_PRINT_QUALITY_DRAFT)
+        data.SetQuality(wxPRINT_QUALITY_DRAFT);
+    else
+        data.SetQuality(wxPRINT_QUALITY_MEDIUM);
+
+    data.SetNoCopies(gtk_print_settings_get_n_copies(m_config));
+
+    data.SetColour(gtk_print_settings_get_use_color(m_config));
+
+    switch (gtk_print_settings_get_duplex(m_config))
+    {
+        case GTK_PRINT_DUPLEX_SIMPLEX:      data.SetDuplex (wxDUPLEX_SIMPLEX);
+                                            break;
+
+        case GTK_PRINT_DUPLEX_HORIZONTAL:   data.SetDuplex (wxDUPLEX_HORIZONTAL);
+                                            break;
+
+        default:
+        case GTK_PRINT_DUPLEX_VERTICAL:      data.SetDuplex (wxDUPLEX_VERTICAL);
+                                            break;
+    }
+
+    GtkPageOrientation orientation = gtk_print_settings_get_orientation (m_config);
+    if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT)
+    {
+        data.SetOrientation(wxPORTRAIT);
+        data.SetOrientationReversed(false);
+    }
+    else if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE)
+    {
+        data.SetOrientation(wxLANDSCAPE);
+        data.SetOrientationReversed(false);
+    }
+    else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+    {
+        data.SetOrientation(wxPORTRAIT);
+        data.SetOrientationReversed(true);
+    }
+    else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
+    {
+        data.SetOrientation(wxLANDSCAPE);
+        data.SetOrientationReversed(true);
+    }
+
+    data.SetCollate(gtk_print_settings_get_collate (m_config));
+
+    // Paper formats : these are the most common paper formats.
+    GtkPaperSize *paper_size = gtk_print_settings_get_paper_size (m_config);
+    if (!paper_size)
+        data.SetPaperId(wxPAPER_NONE);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new (GTK_PAPER_NAME_A3)))
+        data.SetPaperId(wxPAPER_A3);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new (GTK_PAPER_NAME_A4)))
+        data.SetPaperId(wxPAPER_A4);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new (GTK_PAPER_NAME_A5)))
+        data.SetPaperId(wxPAPER_A5);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new (GTK_PAPER_NAME_B5)))
+        data.SetPaperId(wxPAPER_B5);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new (GTK_PAPER_NAME_LETTER)))
+        data.SetPaperId(wxPAPER_LETTER);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new (GTK_PAPER_NAME_LEGAL)))
+        data.SetPaperId(wxPAPER_LEGAL);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new (GTK_PAPER_NAME_EXECUTIVE)))
+        data.SetPaperId(wxPAPER_EXECUTIVE);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"na_number-10")))
+        data.SetPaperId(wxPAPER_ENV_10);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-c5")))
+        data.SetPaperId(wxPAPER_ENV_C5);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-c6")))
+        data.SetPaperId(wxPAPER_ENV_C6);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"jis-b5")))
+        data.SetPaperId(wxPAPER_B5_TRANSVERSE);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-b5")))
+        data.SetPaperId(wxPAPER_ENV_B5);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"na_monarch")))
+        data.SetPaperId(wxPAPER_ENV_MONARCH);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"engineering-c")))
+        data.SetPaperId( wxPAPER_CSHEET);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"engineering-d")))
+        data.SetPaperId( wxPAPER_DSHEET);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"engineering-e")))
+        data.SetPaperId( wxPAPER_ESHEET);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"letter")))
+        data.SetPaperId( wxPAPER_LETTERSMALL);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"engineering-b")))
+        data.SetPaperId( wxPAPER_TABLOID);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"ledger")))
+        data.SetPaperId( wxPAPER_LEDGER);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"statement")))
+        data.SetPaperId( wxPAPER_STATEMENT);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( GTK_PAPER_NAME_A4 )))
+        data.SetPaperId( wxPAPER_A4SMALL);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-b4")))
+        data.SetPaperId( wxPAPER_B4);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"folio")))
+        data.SetPaperId( wxPAPER_FOLIO);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"quarto")))
+        data.SetPaperId( wxPAPER_QUARTO);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"10x14")))
+        data.SetPaperId( wxPAPER_10X14);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"ledger")))
+        data.SetPaperId( wxPAPER_11X17);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"letter")))
+        data.SetPaperId( wxPAPER_NOTE);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"na-number-9-envelope")))
+        data.SetPaperId( wxPAPER_ENV_9);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"number-11")))
+        data.SetPaperId( wxPAPER_ENV_11);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"number-12")))
+        data.SetPaperId( wxPAPER_ENV_12);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"number-14")))
+        data.SetPaperId( wxPAPER_ENV_14);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-designated")))
+        data.SetPaperId( wxPAPER_ENV_DL);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-c3")))
+        data.SetPaperId( wxPAPER_ENV_C3);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-c4")))
+        data.SetPaperId( wxPAPER_ENV_C4);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"c6/c5")))
+        data.SetPaperId( wxPAPER_ENV_C65);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-b4")))
+        data.SetPaperId( wxPAPER_ENV_B4);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"iso-b6")))
+            data.SetPaperId( wxPAPER_ENV_B6);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"Italian")))
+        data.SetPaperId( wxPAPER_ENV_ITALY);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"personal")))
+        data.SetPaperId( wxPAPER_ENV_PERSONAL);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"fanfold-us")))
+        data.SetPaperId( wxPAPER_FANFOLD_US);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"fanfold-European")))
+        data.SetPaperId( wxPAPER_FANFOLD_STD_GERMAN);
+    else if (gtk_paper_size_is_equal(paper_size,gtk_paper_size_new ( (const gchar*)"foolscap")))
+        data.SetPaperId( wxPAPER_FANFOLD_LGL_GERMAN);
+    else
+        data.SetPaperId(wxPAPER_NONE);
+    return true;
+}
+
+// Put datas given by the wxPrintData into m_config.
+// Called by wxPrintData::ConvertToNative().
+bool wxGtkPrintNativeData::TransferFrom( const wxPrintData &data )
+{
+    if(!m_config)
+        return false;
+
+    wxPrintQuality quality = data.GetQuality();
+    if (quality == wxPRINT_QUALITY_HIGH)
+        gtk_print_settings_set_quality (m_config, GTK_PRINT_QUALITY_HIGH);
+    else if (quality == wxPRINT_QUALITY_MEDIUM)
+        gtk_print_settings_set_quality (m_config, GTK_PRINT_QUALITY_NORMAL);
+    else if (quality == wxPRINT_QUALITY_LOW)
+        gtk_print_settings_set_quality (m_config, GTK_PRINT_QUALITY_LOW);
+    else if (quality == wxPRINT_QUALITY_DRAFT)
+        gtk_print_settings_set_quality (m_config, GTK_PRINT_QUALITY_DRAFT);
+    else if (quality > 1)
+        gtk_print_settings_set_resolution (m_config, quality);
+    else
+        gtk_print_settings_set_quality (m_config, GTK_PRINT_QUALITY_NORMAL);
+
+    gtk_print_settings_set_n_copies(m_config, data.GetNoCopies());
+
+    gtk_print_settings_set_use_color(m_config, data.GetColour());
+
+    switch (data.GetDuplex())
+    {
+        case wxDUPLEX_SIMPLEX:      gtk_print_settings_set_duplex (m_config, GTK_PRINT_DUPLEX_SIMPLEX);
+                                break;
+
+        case wxDUPLEX_HORIZONTAL:   gtk_print_settings_set_duplex (m_config, GTK_PRINT_DUPLEX_HORIZONTAL);
+                                break;
+
+        default:
+        case wxDUPLEX_VERTICAL:      gtk_print_settings_set_duplex (m_config, GTK_PRINT_DUPLEX_VERTICAL);
+                                break;
+    }
+
+    if (!data.IsOrientationReversed())
+    {
+        if (data.GetOrientation() == wxLANDSCAPE)
+            gtk_print_settings_set_orientation (m_config, GTK_PAGE_ORIENTATION_LANDSCAPE);
+        else
+            gtk_print_settings_set_orientation (m_config, GTK_PAGE_ORIENTATION_PORTRAIT);
+    }
+    else {
+        if (data.GetOrientation() == wxLANDSCAPE)
+            gtk_print_settings_set_orientation (m_config, GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
+        else
+            gtk_print_settings_set_orientation (m_config, GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT);
+    }
+
+    gtk_print_settings_set_collate (m_config, data.GetCollate());
+
+    // Paper formats: these are the most common paper formats.
+    switch (data.GetPaperId())
+    {
+        case wxPAPER_A3:        gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new (GTK_PAPER_NAME_A3));
+                                break;
+        case wxPAPER_A4:        gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new (GTK_PAPER_NAME_A4));
+                                break;
+        case wxPAPER_A5:        gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new (GTK_PAPER_NAME_A5));
+                                break;
+        case wxPAPER_B5_TRANSVERSE:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "jis-b5"));
+                                break;
+        case wxPAPER_B5:        gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new (GTK_PAPER_NAME_B5));
+                                break;
+        case wxPAPER_LETTER:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new (GTK_PAPER_NAME_LETTER));
+                                break;
+        case wxPAPER_LEGAL:     gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new (GTK_PAPER_NAME_LEGAL));
+                                break;
+        case wxPAPER_EXECUTIVE: gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new (GTK_PAPER_NAME_EXECUTIVE));
+                                break;
+        case wxPAPER_ENV_10:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "na_number-10"));
+                                break;
+        case wxPAPER_ENV_C5:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-c5"));
+                                break;
+        case wxPAPER_ENV_C6:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-c6"));
+                                break;
+        case wxPAPER_ENV_B5:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-c5b5"));
+                                break;
+        case wxPAPER_ENV_MONARCH:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "na_monarch"));
+                                break;
+        case wxPAPER_CSHEET:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "engineering-c"));
+                                break;
+        case wxPAPER_DSHEET:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "engineering-d"));
+                                break;
+        case wxPAPER_ESHEET:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "engineering-e"));
+                                break;
+        case wxPAPER_LETTERSMALL:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "letter"));
+                                break;
+        case wxPAPER_TABLOID:   gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "engineering-b"));
+                                break;
+        case wxPAPER_LEDGER:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "ledger"));
+                                break;
+        case wxPAPER_STATEMENT:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "statement"));
+                                break;
+        case wxPAPER_A4SMALL:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new (GTK_PAPER_NAME_A4));
+                                break;
+        case wxPAPER_B4:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-b4"));
+                                break;
+        case wxPAPER_FOLIO:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "folio"));
+                                break;
+        case wxPAPER_QUARTO:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "quarto"));
+                                break;
+        case wxPAPER_10X14:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "10x14"));
+                                break;
+        case wxPAPER_11X17:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "ledger"));
+                                break;
+        case wxPAPER_NOTE:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "letter"));
+                                break;
+        case wxPAPER_ENV_9:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "na-number-9-envelope"));
+                                break;
+        case wxPAPER_ENV_11:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "number-11"));
+                                break;
+        case wxPAPER_ENV_12:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "number-12"));
+                                break;
+        case wxPAPER_ENV_14:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "number-14"));
+                                break;
+        case wxPAPER_ENV_DL:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-designated"));
+                                break;
+        case wxPAPER_ENV_C3:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-c3"));
+                                break;
+        case wxPAPER_ENV_C4:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-c4"));
+                                break;
+        case wxPAPER_ENV_C65:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "c6/c5"));
+                                break;
+        case wxPAPER_ENV_B4:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-b4"));
+                                break;
+        case wxPAPER_ENV_B6:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "iso-b6"));
+                                break;
+        case wxPAPER_ENV_ITALY:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "Italian"));
+                                break;
+        case wxPAPER_ENV_PERSONAL:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "personal"));
+                                break;
+        case wxPAPER_FANFOLD_US:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "fanfold-us"));
+                                break;
+        case wxPAPER_FANFOLD_STD_GERMAN:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "fanfold-European"));
+                                break;
+        case wxPAPER_FANFOLD_LGL_GERMAN:    gtk_print_settings_set_paper_size(m_config, gtk_paper_size_new ((const gchar*) "foolscap"));
+                                break;
+        case wxPAPER_NONE:
+        default:                break;
+    }
+
+    return true;
+}
+
+void wxGtkPrintNativeData::SetPrintConfig( GtkPrintSettings * config )
+{
+    if (config)
+        m_config = gtk_print_settings_copy(config);
+}
+
+// Extract page setup from settings.
+GtkPageSetup* wxGtkPrintNativeData::GetPageSetupFromSettings(GtkPrintSettings* settings)
+{
+    GtkPageSetup* page_setup = gtk_page_setup_new();
+       gtk_page_setup_set_orientation (page_setup, gtk_print_settings_get_orientation (settings));
+
+       GtkPaperSize *paper_size = gtk_print_settings_get_paper_size (settings);
+       if (paper_size != NULL)
+               gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
+
+    return page_setup;
+}
+
+// Insert page setup into a given GtkPrintSettings.
+void wxGtkPrintNativeData::SetPageSetupToSettings(GtkPrintSettings* settings, GtkPageSetup* page_setup)
+{
+    gtk_print_settings_set_orientation ( settings, gtk_page_setup_get_orientation (page_setup));
+       gtk_print_settings_set_paper_size ( settings, gtk_page_setup_get_paper_size (page_setup));
+}
+
+//----------------------------------------------------------------------------
+// wxGtkPrintDialog
+//----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGtkPrintDialog, wxPrintDialogBase)
+
+wxGtkPrintDialog::wxGtkPrintDialog( wxWindow *parent, wxPrintDialogData *data )
+                    : wxPrintDialogBase(parent, wxID_ANY, _("Print"),
+                               wxPoint(0, 0), wxSize(600, 600),
+                               wxDEFAULT_DIALOG_STYLE |
+                               wxTAB_TRAVERSAL)
+{
+    if (data)
+        m_printDialogData = *data;
+
+    m_parent = parent;
+    SetShowDialog(true);
+}
+
+wxGtkPrintDialog::wxGtkPrintDialog( wxWindow *parent, wxPrintData *data )
+                    : wxPrintDialogBase(parent, wxID_ANY, _("Print"),
+                               wxPoint(0, 0), wxSize(600, 600),
+                               wxDEFAULT_DIALOG_STYLE |
+                               wxTAB_TRAVERSAL)
+{
+    if (data)
+        m_printDialogData = *data;
+
+    m_parent = parent;
+    SetShowDialog(true);
+}
+
+
+wxGtkPrintDialog::~wxGtkPrintDialog()
+{
+}
+
+// This is called even if we actually don't want the dialog to appear.
+int wxGtkPrintDialog::ShowModal()
+{
+    GtkPrintOperationResult response;
+
+    // We need to restore the settings given in the constructor.
+    wxPrintData data = m_printDialogData.GetPrintData();
+    wxGtkPrintNativeData *native =
+      (wxGtkPrintNativeData*) data.GetNativeData();
+    data.ConvertToNative();
+
+    GtkPrintSettings * settings = native->GetPrintConfig();
+
+    // We have to restore pages to print here because they're stored in a wxPrintDialogData and ConvertToNative only works for wxPrintData.
+    int fromPage = m_printDialogData.GetFromPage();
+    int toPage = m_printDialogData.GetToPage();
+    if (m_printDialogData.GetSelection())
+        gtk_print_settings_set_print_pages(settings, GTK_PRINT_PAGES_CURRENT);
+    else if (m_printDialogData.GetAllPages())
+        gtk_print_settings_set_print_pages(settings, GTK_PRINT_PAGES_ALL);
+    else {
+        gtk_print_settings_set_print_pages(settings, GTK_PRINT_PAGES_RANGES);
+        GtkPageRange *range;
+        range = g_new (GtkPageRange, 1);
+        range[0].start = fromPage-1;
+        range[0].end = (toPage >= fromPage) ? toPage-1 : fromPage-1;
+        gtk_print_settings_set_page_ranges (settings, range, 1);
+    }
+
+    // If the settings are OK, we restore it.
+    if (settings != NULL)
+        gtk_print_operation_set_print_settings (native->GetPrintJob(), settings);
+        gtk_print_operation_set_default_page_setup (native->GetPrintJob(), native->GetPageSetupFromSettings(settings));
+
+    // Show the dialog if needed.
+    GError* gError = NULL;
+    if (GetShowDialog())
+        response = gtk_print_operation_run (native->GetPrintJob(), GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW(gtk_widget_get_toplevel(m_parent->m_widget) ), &gError);
+    else
+        response = gtk_print_operation_run (native->GetPrintJob(), GTK_PRINT_OPERATION_ACTION_PRINT, (GtkWindow *) m_parent, &gError);
+
+    // Does everything went well?
+    if (response == GTK_PRINT_OPERATION_RESULT_CANCEL)
+    {
+        return wxID_CANCEL;
+    }
+    else if (response == GTK_PRINT_OPERATION_RESULT_ERROR)
+    {
+        g_error_free (gError);
+        wxLogError(_("Error while printing: ") + wxString::Format(_("%s"), gError->message));
+        return wxID_NO; // We use wxID_NO because there is no wxID_ERROR available
+    }
+
+    // Now get the settings and save it.
+    GtkPrintSettings* newSettings = gtk_print_operation_get_print_settings (native->GetPrintJob());
+    native->SetPrintConfig(newSettings);
+    data.ConvertFromNative();
+
+    // Same problem as a few lines before.
+    switch (gtk_print_settings_get_print_pages(newSettings))
+    {
+        case GTK_PRINT_PAGES_CURRENT:
+            m_printDialogData.SetSelection( true );
+            break;
+        case GTK_PRINT_PAGES_ALL:
+            m_printDialogData.SetAllPages( true );
+            m_printDialogData.SetFromPage( 0 );
+            m_printDialogData.SetToPage( 9999 );
+            break;
+        case GTK_PRINT_PAGES_RANGES:
+        default:
+            // wxWidgets doesn't support multiple ranges, so we can only save the first one even if the user wants to print others.
+            // For example, the user enters "1-3;5-7" in the dialog: pages 1-3 and 5-7 will be correctly printed when the user
+            // will hit "OK" button. However we can only save 1-3 in the print data.
+            gint num_ranges = 0;
+            GtkPageRange* range;
+            range = gtk_print_settings_get_page_ranges (newSettings, &num_ranges);
+            m_printDialogData.SetFromPage( range[0].start );
+            m_printDialogData.SetToPage( range[0].end );
+            break;
+    }
+
+    return wxID_OK;
+}
+
+//----------------------------------------------------------------------------
+// wxGtkPageSetupDialog
+//----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGtkPageSetupDialog, wxPageSetupDialogBase)
+
+wxGtkPageSetupDialog::wxGtkPageSetupDialog( wxWindow *parent,
+                            wxPageSetupDialogData* data )
+{
+    if (data)
+        m_pageDialogData = *data;
+
+    m_parent = parent;
+}
+
+wxGtkPageSetupDialog::~wxGtkPageSetupDialog()
+{
+}
+
+int wxGtkPageSetupDialog::ShowModal()
+{
+    // Get the config.
+    m_pageDialogData.GetPrintData().ConvertToNative();
+    wxGtkPrintNativeData *native = (wxGtkPrintNativeData*) m_pageDialogData.GetPrintData().GetNativeData();
+    GtkPrintSettings* nativeData = native->GetPrintConfig();
+
+    // We only need the pagesetup data which are part of the settings.
+    GtkPageSetup* oldPageSetup = native->GetPageSetupFromSettings(nativeData);
+
+    // If the user used a custom paper format the last time he printed, we have to restore it too.
+    if (m_pageDialogData.GetPrintData().GetPaperId() == wxPAPER_NONE)
+    {
+        wxSize customPaperSize = m_pageDialogData.GetPaperSize();
+        if (customPaperSize.GetWidth() > 0 && customPaperSize.GetHeight() > 0)
+        {
+            wxString title = _("Custom size");
+            GtkPaperSize* customSize = gtk_paper_size_new_custom ("custom", title.mb_str(), (gdouble) customPaperSize.GetWidth(), (gdouble) customPaperSize.GetHeight(), GTK_UNIT_MM);
+            gtk_page_setup_set_paper_size_and_default_margins (oldPageSetup, customSize);
+            g_object_unref(customSize);
+        }
+    }
+
+    // Now show the dialog.
+    GtkPageSetup* newPageSetup = gtk_print_run_page_setup_dialog (GTK_WINDOW(m_parent->m_widget),
+                                                           oldPageSetup,
+                                                           nativeData);
+
+    int ret;
+    if (newPageSetup != oldPageSetup)
+    {
+        native->SetPageSetupToSettings(nativeData, newPageSetup);
+        m_pageDialogData.GetPrintData().ConvertFromNative();
+
+        // Store custom paper format if any.
+        if (m_pageDialogData.GetPrintData().GetPaperId() == wxPAPER_NONE)
+        {
+            gdouble ml,mr,mt,mb,pw,ph;
+            ml = gtk_page_setup_get_left_margin (newPageSetup, GTK_UNIT_MM);
+            mr = gtk_page_setup_get_right_margin (newPageSetup, GTK_UNIT_MM);
+            mt = gtk_page_setup_get_top_margin (newPageSetup, GTK_UNIT_MM);
+            mb = gtk_page_setup_get_bottom_margin (newPageSetup, GTK_UNIT_MM);
+
+            pw = gtk_page_setup_get_paper_width (newPageSetup, GTK_UNIT_MM);
+            ph = gtk_page_setup_get_paper_height (newPageSetup, GTK_UNIT_MM);
+
+            m_pageDialogData.SetMarginTopLeft( wxPoint( (int)(ml+0.5), (int)(mt+0.5)) );
+            m_pageDialogData.SetMarginBottomRight( wxPoint( (int)(mr+0.5), (int)(mb+0.5)) );
+
+            m_pageDialogData.SetPaperSize( wxSize( (int)(pw+0.5), (int)(ph+0.5) ) );
+        }
+
+        ret = wxID_OK;
+    }
+    else
+    {
+        ret = wxID_CANCEL;
+    }
+
+    return ret;
+}
+
+//----------------------------------------------------------------------------
+// wxGtkPrinter
+//----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGtkPrinter, wxPrinterBase)
+
+wxGtkPrinter::wxGtkPrinter( wxPrintDialogData *data ) :
+    wxPrinterBase( data )
+{
+    m_gpc = NULL;
+
+    if (data)
+        m_printDialogData = *data;
+}
+
+wxGtkPrinter::~wxGtkPrinter()
+{
+}
+
+bool wxGtkPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt )
+{
+    if (!printout)
+    {
+        sm_lastError = wxPRINTER_ERROR;
+        return false;
+    }
+
+    // Let's correct the PageInfo just in case the app gives wrong values.
+    int fromPage, toPage;
+    int minPage, maxPage;
+    printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
+    m_printDialogData.SetAllPages(true);
+
+    if (minPage < 1) minPage = 1;
+    if (maxPage < 1) maxPage = 9999;
+    if (maxPage < minPage) maxPage = minPage;
+
+    m_printDialogData.SetMinPage(minPage);
+    m_printDialogData.SetMaxPage(maxPage);
+    if (fromPage != 0)
+    {
+        if (fromPage < minPage) fromPage = minPage;
+        else if (fromPage > maxPage) fromPage = maxPage;
+        m_printDialogData.SetFromPage(fromPage);
+    }
+    if (toPage != 0)
+    {
+        m_printDialogData.SetToPage(toPage);
+        if (toPage > maxPage) toPage = maxPage;
+        else if (toPage < minPage) toPage = minPage;
+    }
+
+    if (((minPage != fromPage) && fromPage != 0) || ((maxPage != toPage) && toPage != 0)) m_printDialogData.SetAllPages(false);
+
+
+    wxPrintData printdata = GetPrintDialogData().GetPrintData();
+    wxGtkPrintNativeData *native = (wxGtkPrintNativeData*) printdata.GetNativeData();
+
+    GtkPrintOperation *printOp = gtk_print_operation_new ();
+
+    native->SetPrintJob( printOp );
+
+    printout->SetIsPreview(false);
+
+    wxPrinterToGtkData dataToSend;
+    dataToSend.printer = this;
+    dataToSend.printout = printout;
+
+    // These Gtk signals are catched here.
+    g_signal_connect (printOp, "begin-print", G_CALLBACK (gtk_begin_print_callback), &dataToSend);
+    g_signal_connect (printOp, "draw-page", G_CALLBACK (gtk_draw_page_print_callback), &dataToSend);
+    g_signal_connect (printOp, "end-print", G_CALLBACK (gtk_end_print_callback), printout);
+    g_signal_connect (printOp, "preview", G_CALLBACK (gtk_preview_print_callback), printout);
+
+    m_showDialog = true;
+    if (!prompt)
+        m_showDialog = false;
+
+    // PrintDialog returns a wxDC but we created it before so we don't need it anymore: we just delete it.
+    wxDC* uselessdc = PrintDialog( parent );
+    delete uselessdc;
+
+    g_object_unref (printOp);
+
+    return (sm_lastError == wxPRINTER_NO_ERROR);
+}
+
+void wxGtkPrinter::BeginPrint(wxPrintout *printout, GtkPrintOperation *operation, GtkPrintContext *context)
+{
+    wxPrintData printdata = GetPrintDialogData().GetPrintData();
+    wxGtkPrintNativeData *native = (wxGtkPrintNativeData*) printdata.GetNativeData();
+
+    SetPrintContext(context);
+    native->SetPrintContext( context );
+
+    m_dc = new wxGtkPrintDC( printdata );
+
+    if (!m_dc->IsOk())
+    {
+        if (sm_lastError != wxPRINTER_CANCELLED)
+        {
+            sm_lastError = wxPRINTER_ERROR;
+            wxFAIL_MSG(_("The wxGtkPrintDC cannot be used."));
+        }
+        return;
+    }
+    wxSize ScreenPixels = wxGetDisplaySize();
+    wxSize ScreenMM = wxGetDisplaySizeMM();
+
+    printout->SetPPIScreen( (int) ((ScreenPixels.GetWidth() * 25.4) / ScreenMM.GetWidth()),
+                            (int) ((ScreenPixels.GetHeight() * 25.4) / ScreenMM.GetHeight()) );
+    printout->SetPPIPrinter( wxGtkPrintDC::GetResolution(),
+                             wxGtkPrintDC::GetResolution() );
+
+    printout->SetDC(m_dc);
+
+    int w, h;
+    m_dc->GetSize(&w, &h);
+    printout->SetPageSizePixels((int)w, (int)h);
+    printout->SetPaperRectPixels(wxRect(0, 0, w, h));
+    int mw, mh;
+    m_dc->GetSizeMM(&mw, &mh);
+    printout->SetPageSizeMM((int)mw, (int)mh);
+    printout->OnPreparePrinting();
+
+    // Get some parameters from the printout, if defined.
+    int fromPage, toPage;
+    int minPage, maxPage;
+    printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
+
+    if (maxPage == 0)
+    {
+        sm_lastError = wxPRINTER_ERROR;
+        wxFAIL_MSG(_("wxPrintout::GetPageInfo gives a null maxPage."));
+        return;
+    }
+
+    printout->OnBeginPrinting();
+
+    int numPages = 0;
+
+    // If we're not previewing we need to calculate the number of pages to print.
+    // If we're previewing, Gtk Print will render every pages without wondering about the page ranges the user may
+    // have defined in the dialog. So the number of pages is the maximum available.
+    if (!printout->IsPreview())
+    {
+        GtkPrintSettings * settings = gtk_print_operation_get_print_settings (operation);
+        switch (gtk_print_settings_get_print_pages(settings))
+        {
+            case GTK_PRINT_PAGES_CURRENT:
+                numPages = 1;
+                break;
+            case GTK_PRINT_PAGES_RANGES:
+                {gint num_ranges = 0;
+                GtkPageRange* range;
+                int i;
+                range = gtk_print_settings_get_page_ranges (settings, &num_ranges);
+                for (i=0; i<num_ranges; i++)
+                {
+                    if (range[i].end < range[i].start) range[i].end = range[i].start;
+                    if (range[i].start < minPage-1) range[i].start = minPage-1;
+                    if (range[i].end > maxPage-1) range[i].end = maxPage-1;
+                    if (range[i].start > maxPage-1) range[i].start = maxPage-1;
+                    numPages += range[i].end - range[i].start + 1;
+                }
+                gtk_print_settings_set_page_ranges (settings, range, 1);
+                break;}
+            case GTK_PRINT_PAGES_ALL:
+            default:
+                numPages = maxPage - minPage + 1;
+                break;
+        }
+    }
+    else numPages = maxPage - minPage + 1;
+
+    gtk_print_operation_set_n_pages(operation, numPages);
+}
+
+void wxGtkPrinter::DrawPage(wxPrintout *printout, GtkPrintOperation *operation, GtkPrintContext *context, int page_nr)
+{
+    int fromPage, toPage, minPage, maxPage, startPage, endPage;
+    printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
+
+    int numPageToDraw = page_nr + minPage;
+    if (numPageToDraw < minPage) numPageToDraw = minPage;
+    if (numPageToDraw > maxPage) numPageToDraw = maxPage;
+
+    GtkPrintSettings * settings = gtk_print_operation_get_print_settings (operation);
+    switch (gtk_print_settings_get_print_pages(settings))
+    {
+        case GTK_PRINT_PAGES_CURRENT:
+            g_object_get_property((GObject*) operation, (const gchar *) "current-page", (GValue*) &startPage);
+            g_object_get_property((GObject*) operation, (const gchar *) "current-page", (GValue*) &endPage);
+            break;
+        case GTK_PRINT_PAGES_RANGES:
+            {gint num_ranges = 0;
+            GtkPageRange* range;
+            range = gtk_print_settings_get_page_ranges (settings, &num_ranges);
+            // We don't need to verify these values as it has already been done in wxGtkPrinter::BeginPrint.
+            startPage = range[0].start + 1;
+            endPage = range[0].end + 1;
+            break;}
+        case GTK_PRINT_PAGES_ALL:
+        default:
+            startPage = minPage;
+            endPage = maxPage;
+            break;
+    }
+
+    if(numPageToDraw == startPage)
+    {
+        if (!printout->OnBeginDocument(startPage, endPage))
+        {
+            wxLogError(_("Could not start printing."));
+            sm_lastError = wxPRINTER_ERROR;
+        }
+    }
+
+    // The app can render the page numPageToDraw.
+    if (printout->HasPage(numPageToDraw))
+    {
+        m_dc->StartPage();
+        printout->OnPrintPage(numPageToDraw);
+        m_dc->EndPage();
+    }
+
+
+    if(numPageToDraw == endPage)
+    {
+        printout->OnEndDocument();
+    }
+}
+
+wxDC* wxGtkPrinter::PrintDialog( wxWindow *parent )
+{
+    wxGtkPrintDialog dialog( parent, &m_printDialogData );
+    int ret;
+
+    dialog.SetPrintDC(m_dc);
+
+    dialog.SetShowDialog(m_showDialog);
+
+    ret = dialog.ShowModal();
+
+    if (ret == wxID_CANCEL)
+    {
+        sm_lastError = wxPRINTER_CANCELLED;
+        return NULL;
+    }
+    if (ret == wxID_NO)
+    {
+        sm_lastError = wxPRINTER_ERROR;
+        wxFAIL_MSG(_("The print dialog returned an error."));
+        return NULL;
+    }
+
+    m_printDialogData = dialog.GetPrintDialogData();
+    return new wxGtkPrintDC( m_printDialogData.GetPrintData() );
+}
+
+bool wxGtkPrinter::Setup( wxWindow *parent )
+{
+    // Obsolete, for backward compatibility.
+    return false;
+}
+
+//-----------------------------------------------------------------------------
+// wxGtkPrintDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGtkPrintDC, wxDC)
+
+// Define the default resolution for this DC. This resolution is just used for positioning as the cairo context is scalable.
+int wxGtkPrintDC::ms_resolution = 72;
+
+wxGtkPrintDC::wxGtkPrintDC( const wxPrintData& data )
+{
+    m_printData = data;
+
+    wxGtkPrintNativeData *native =
+        (wxGtkPrintNativeData*) m_printData.GetNativeData();
+
+    m_gpc = native->GetPrintContext();
+
+    ms_resolution = (int) gtk_print_context_get_dpi_x(m_gpc);
+    m_context = gtk_print_context_create_pango_context( m_gpc );
+    m_layout = gtk_print_context_create_pango_layout ( m_gpc );
+    m_fontdesc = pango_font_description_from_string( "Sans 12" );
+
+    m_cairo = gtk_print_context_get_cairo_context ( m_gpc );
+
+    m_currentRed = 0;
+    m_currentBlue = 0;
+    m_currentGreen = 0;
+
+    m_signX =  1;  // default x-axis left to right.
+    m_signY = 1;  // default y-axis bottom up -> top down.
+
+    GetSize( &m_deviceOffsetX, &m_deviceOffsetY );
+}
+
+wxGtkPrintDC::~wxGtkPrintDC()
+{
+    g_object_unref(m_context);
+    g_object_unref(m_layout);
+}
+
+bool wxGtkPrintDC::IsOk() const
+{
+    return true;
+}
+
+void wxGtkPrintDC::ComputeScaleAndOrigin()
+{
+    // Called when the scale and/or origin of the context has to be changed.
+    m_scaleX = m_logicalScaleX * m_userScaleX;
+    m_scaleY = m_logicalScaleY * m_userScaleY;
+
+    cairo_translate(m_cairo, m_deviceOriginX, m_deviceOriginY);
+    cairo_scale(m_cairo, m_scaleX, m_scaleY );
+}
+
+bool wxGtkPrintDC::DoFloodFill(wxCoord x1, wxCoord y1, const wxColour &col, int style )
+{
+    // We can't access the given coord as a cairo context is scalable, ie a coord doesn't mean anything in this context.
+    wxFAIL_MSG(_("not implemented"));
+    return false;
+}
+
+void wxGtkPrintDC::DoGradientFillConcentric(const wxRect& rect, const wxColour& initialColour, const wxColour& destColour, const wxPoint& circleCenter)
+{
+    wxCoord xC = circleCenter.x;
+    wxCoord yC = circleCenter.y;
+    wxCoord xR = rect.x;
+    wxCoord yR = rect.y;
+    wxCoord w =  rect.width;
+    wxCoord h = rect.height;
+
+    double radius = sqrt((w/2)*(w/2)+(h/2)*(h/2));
+
+    unsigned char redI = initialColour.Red();
+    unsigned char blueI = initialColour.Blue();
+    unsigned char greenI = initialColour.Green();
+    unsigned char alphaI = initialColour.Alpha();
+    unsigned char redD = destColour.Red();
+    unsigned char blueD = destColour.Blue();
+    unsigned char greenD = destColour.Green();
+    unsigned char alphaD = destColour.Alpha();
+
+    double redIPS = (double)(redI) / 255.0;
+    double blueIPS = (double)(blueI) / 255.0;
+    double greenIPS = (double)(greenI) / 255.0;
+    double alphaIPS = (double)(alphaI) / 255.0;
+    double redDPS = (double)(redD) / 255.0;
+    double blueDPS = (double)(blueD) / 255.0;
+    double greenDPS = (double)(greenD) / 255.0;
+    double alphaDPS = (double)(alphaD) / 255.0;
+
+    // Create a pattern with the gradient.
+    cairo_pattern_t* gradient;
+    gradient = cairo_pattern_create_radial (LogicalToDeviceX(xC+xR), LogicalToDeviceY(yC+yR), 0, LogicalToDeviceX(xC+xR), LogicalToDeviceY(yC+yR), radius);
+    cairo_pattern_add_color_stop_rgba (gradient, 0.0, redIPS, greenIPS, blueIPS, alphaIPS);
+    cairo_pattern_add_color_stop_rgba (gradient, 1.0, redDPS, greenDPS, blueDPS, alphaDPS);
+
+    // Fill the rectangle with this pattern.
+    cairo_set_source(m_cairo, gradient);
+    cairo_rectangle (m_cairo, LogicalToDeviceX(xR), LogicalToDeviceY(yR), LogicalToDeviceXRel(w), LogicalToDeviceYRel(h) );
+    cairo_fill(m_cairo);
+
+    cairo_pattern_destroy(gradient);
+
+    CalcBoundingBox(xR, yR);
+    CalcBoundingBox(xR+w, yR+h);
+}
+
+void wxGtkPrintDC::DoGradientFillLinear(const wxRect& rect, const wxColour& initialColour, const wxColour& destColour, wxDirection nDirection)
+{
+    wxCoord x = rect.x;
+    wxCoord y = rect.y;
+    wxCoord w = rect.width;
+    wxCoord h = rect.height;
+
+    unsigned char redI = initialColour.Red();
+    unsigned char blueI = initialColour.Blue();
+    unsigned char greenI = initialColour.Green();
+    unsigned char alphaI = initialColour.Alpha();
+    unsigned char redD = destColour.Red();
+    unsigned char blueD = destColour.Blue();
+    unsigned char greenD = destColour.Green();
+    unsigned char alphaD = destColour.Alpha();
+
+    double redIPS = (double)(redI) / 255.0;
+    double blueIPS = (double)(blueI) / 255.0;
+    double greenIPS = (double)(greenI) / 255.0;
+    double alphaIPS = (double)(alphaI) / 255.0;
+    double redDPS = (double)(redD) / 255.0;
+    double blueDPS = (double)(blueD) / 255.0;
+    double greenDPS = (double)(greenD) / 255.0;
+    double alphaDPS = (double)(alphaD) / 255.0;
+
+    // Create a pattern with the gradient.
+    cairo_pattern_t* gradient;
+    gradient = cairo_pattern_create_linear (LogicalToDeviceX(x), LogicalToDeviceY(y), LogicalToDeviceX(x+w), LogicalToDeviceY(y));
+
+    if (nDirection == wxWEST)
+    {
+        cairo_pattern_add_color_stop_rgba (gradient, 0.0, redDPS, greenDPS, blueDPS, alphaDPS);
+        cairo_pattern_add_color_stop_rgba (gradient, 1.0, redIPS, greenIPS, blueIPS, alphaIPS);
+    }
+    else {
+        cairo_pattern_add_color_stop_rgba (gradient, 0.0, redIPS, greenIPS, blueIPS, alphaIPS);
+        cairo_pattern_add_color_stop_rgba (gradient, 1.0, redDPS, greenDPS, blueDPS, alphaDPS);
+    }
+
+    // Fill the rectangle with this pattern.
+    cairo_set_source(m_cairo, gradient);
+    cairo_rectangle (m_cairo, LogicalToDeviceX(x), LogicalToDeviceY(y), LogicalToDeviceXRel(w), LogicalToDeviceYRel(h) );
+    cairo_fill(m_cairo);
+
+    cairo_pattern_destroy(gradient);
+
+    CalcBoundingBox(x, y);
+    CalcBoundingBox(x+w, y+h);
+}
+
+bool wxGtkPrintDC::DoGetPixel(wxCoord x1, wxCoord y1, wxColour *col) const
+{
+    // We can't access the given coord as a cairo context is scalable, ie a coord doesn't mean anything in this context.
+    wxFAIL_MSG(_("not implemented"));
+    return false;
+}
+
+void wxGtkPrintDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
+{
+    if  (m_pen.GetStyle() == wxTRANSPARENT) return;
+
+    SetPen( m_pen );
+    cairo_move_to ( m_cairo, LogicalToDeviceX(x1), LogicalToDeviceY(y1) );
+    cairo_line_to ( m_cairo, LogicalToDeviceX(x2), LogicalToDeviceY(y2) );
+    cairo_stroke ( m_cairo );
+
+    CalcBoundingBox( x1, y1 );
+    CalcBoundingBox( x2, y2 );
+}
+
+void wxGtkPrintDC::DoCrossHair(wxCoord x, wxCoord y)
+{
+    int *w, *h;
+    w = new int;
+    h = new int;
+    DoGetSize(w, h);
+
+    SetPen(m_pen);
+
+    cairo_move_to (m_cairo, LogicalToDeviceX(x), 0);
+    cairo_line_to (m_cairo, LogicalToDeviceX(x), *h);
+    cairo_move_to (m_cairo, 0, LogicalToDeviceY(y));
+    cairo_line_to (m_cairo, *w, LogicalToDeviceY(y));
+
+    cairo_stroke (m_cairo);
+    CalcBoundingBox( 0, 0 );
+    CalcBoundingBox( *w, *h );
+
+    delete w;
+    delete h;
+}
+
+void wxGtkPrintDC::DoDrawArc(wxCoord x1,wxCoord y1,wxCoord x2,wxCoord y2,wxCoord xc,wxCoord yc)
+{
+    double dx = x1 - xc;
+    double dy = y1 - yc;
+    double radius = sqrt((double)(dx*dx+dy*dy));
+
+    double alpha1, alpha2;
+    if (x1 == x2 && y1 == y2)
+    {
+        alpha1 = 0.0;
+        alpha2 = 360.0;
+    }
+    else
+    if (radius == 0.0)
+    {
+        alpha1 = alpha2 = 0.0;
+    }
+    else
+    {
+        alpha1 = (x1 - xc == 0) ?
+            (y1 - yc < 0) ? 90.0 : -90.0 :
+            atan2(double(y1-yc), double(x1-xc)) * RAD2DEG;
+        alpha2 = (x2 - xc == 0) ?
+            (y2 - yc < 0) ? 90.0 : -90.0 :
+            atan2(double(y2-yc), double(x2-xc)) * RAD2DEG;
+
+        while (alpha1 <= 0)   alpha1 += 360;
+        while (alpha2 <= 0)   alpha2 += 360; // adjust angles to be between.
+        while (alpha1 > 360)  alpha1 -= 360; // 0 and 360 degree.
+        while (alpha2 > 360)  alpha2 -= 360;
+    }
+
+    alpha1 *= DEG2RAD;
+    alpha2 *= DEG2RAD;
+
+    cairo_arc_negative ( m_cairo, LogicalToDeviceX(xc), LogicalToDeviceY(yc), LogicalToDeviceXRel((int)radius), alpha1, alpha2);
+    cairo_line_to(m_cairo, LogicalToDeviceX(xc), LogicalToDeviceY(yc));
+    cairo_close_path (m_cairo);
+
+    SetBrush( m_brush );
+    cairo_fill_preserve( m_cairo );
+
+    SetPen (m_pen);
+    cairo_stroke( m_cairo );
+
+    CalcBoundingBox (x1, y1);
+    CalcBoundingBox (xc, yc);
+    CalcBoundingBox (x2, y2);
+}
+
+void wxGtkPrintDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
+{
+    cairo_save( m_cairo );
+
+    cairo_translate( m_cairo, LogicalToDeviceX((wxCoord) (x + w / 2.)), LogicalToDeviceX((wxCoord) (y + h / 2.)) );
+    double scale = (double)LogicalToDeviceYRel(h) / (double) LogicalToDeviceXRel(w);
+    cairo_scale( m_cairo, 1.0, scale );
+
+    cairo_arc_negative ( m_cairo, 0, 0, LogicalToDeviceXRel(w/2), -sa*DEG2RAD, -ea*DEG2RAD);
+
+    SetPen (m_pen);
+    cairo_stroke_preserve( m_cairo );
+
+    cairo_line_to(m_cairo, 0,0);
+
+    SetBrush( m_brush );
+    cairo_fill( m_cairo );
+
+    cairo_restore( m_cairo );
+
+    CalcBoundingBox( x, y);
+    CalcBoundingBox( x+w, y+h );
+}
+
+void wxGtkPrintDC::DoDrawPoint(wxCoord x, wxCoord y)
+{
+    if  (m_pen.GetStyle() == wxTRANSPARENT) return;
+
+    SetPen( m_pen );
+
+    cairo_move_to ( m_cairo, LogicalToDeviceX(x), LogicalToDeviceY(y) );
+    cairo_line_to ( m_cairo, LogicalToDeviceX(x), LogicalToDeviceY(y) );
+    cairo_stroke ( m_cairo );
+
+    CalcBoundingBox( x, y );
+}
+
+void wxGtkPrintDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
+{
+    if (m_pen.GetStyle() == wxTRANSPARENT) return;
+
+    if (n <= 0) return;
+
+    SetPen (m_pen);
+
+    int i;
+    for ( i =0; i<n ; i++ )
+        CalcBoundingBox( points[i].x+xoffset, points[i].y+yoffset);
+
+    cairo_move_to ( m_cairo, LogicalToDeviceX(points[0].x+xoffset), LogicalToDeviceY(points[0].y+yoffset) );
+
+    for (i = 1; i < n; i++)
+        cairo_line_to ( m_cairo, LogicalToDeviceX(points[i].x+xoffset), LogicalToDeviceY(points[i].y+yoffset) );
+
+    cairo_stroke ( m_cairo);
+}
+
+void wxGtkPrintDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int fillStyle)
+{
+    if (n==0) return;
+
+    cairo_save(m_cairo);
+    if (fillStyle == wxWINDING_RULE)
+        cairo_set_fill_rule( m_cairo, CAIRO_FILL_RULE_WINDING);
+    else
+        cairo_set_fill_rule( m_cairo, CAIRO_FILL_RULE_EVEN_ODD);
+
+    int x = points[0].x + xoffset;
+    int y = points[0].y + yoffset;
+    cairo_new_path(m_cairo);
+    cairo_move_to( m_cairo, LogicalToDeviceX(x), LogicalToDeviceY(y) );
+    int i;
+    for (i = 1; i < n; i++)
+    {
+        int x = points[i].x + xoffset;
+        int y = points[i].y + yoffset;
+        cairo_line_to( m_cairo, LogicalToDeviceX(x), LogicalToDeviceY(y) );
+    }
+    cairo_close_path(m_cairo);
+
+    SetBrush( m_brush );
+    cairo_fill_preserve( m_cairo );
+
+    SetPen (m_pen);
+    cairo_stroke( m_cairo );
+
+    CalcBoundingBox( x, y );
+
+    cairo_restore(m_cairo);
+}
+
+void wxGtkPrintDC::DoDrawPolyPolygon(int n, int count[], wxPoint points[], wxCoord xoffset, wxCoord yoffset, int fillStyle)
+{
+    wxDC::DoDrawPolyPolygon( n, count, points, xoffset, yoffset, fillStyle );
+}
+
+void wxGtkPrintDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
+{
+    cairo_rectangle ( m_cairo, LogicalToDeviceX(x), LogicalToDeviceY(y), LogicalToDeviceXRel(width), LogicalToDeviceYRel(height));
+
+    SetBrush( m_brush );
+    cairo_fill_preserve( m_cairo );
+
+    SetPen (m_pen);
+    cairo_stroke( m_cairo );
+
+    CalcBoundingBox( x, y );
+    CalcBoundingBox( x + width, y + height );
+}
+
+void wxGtkPrintDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius)
+{
+    if (radius < 0.0) radius = - radius * ((width < height) ? width : height);
+
+    wxCoord dd = 2 * (wxCoord) radius;
+    if (dd > width) dd = width;
+    if (dd > height) dd = height;
+    radius = dd / 2;
+
+    wxCoord rad = (wxCoord) radius;
+
+    cairo_new_path(m_cairo);
+    cairo_move_to(m_cairo,LogicalToDeviceX(x + rad),LogicalToDeviceY(y));
+    cairo_curve_to(m_cairo,
+                                LogicalToDeviceX(x + rad),LogicalToDeviceY(y),
+                                LogicalToDeviceX(x),LogicalToDeviceY(y),
+                                LogicalToDeviceX(x),LogicalToDeviceY(y + rad));
+    cairo_line_to(m_cairo,LogicalToDeviceX(x),LogicalToDeviceY(y + height - rad));
+    cairo_curve_to(m_cairo,
+                                LogicalToDeviceX(x),LogicalToDeviceY(y + height - rad),
+                                LogicalToDeviceX(x),LogicalToDeviceY(y + height),
+                                LogicalToDeviceX(x + rad),LogicalToDeviceY(y + height));
+    cairo_line_to(m_cairo,LogicalToDeviceX(x + width - rad),LogicalToDeviceY(y + height));
+    cairo_curve_to(m_cairo,
+                                LogicalToDeviceX(x + width - rad),LogicalToDeviceY(y + height),
+                                LogicalToDeviceX(x + width),LogicalToDeviceY(y + height),
+                                LogicalToDeviceX(x + width),LogicalToDeviceY(y + height - rad));
+    cairo_line_to(m_cairo,LogicalToDeviceX(x + width),LogicalToDeviceY(y + rad));
+    cairo_curve_to(m_cairo,
+                                LogicalToDeviceX(x + width),LogicalToDeviceY(y + rad),
+                                LogicalToDeviceX(x + width),LogicalToDeviceY(y),
+                                LogicalToDeviceX(x + width - rad),LogicalToDeviceY(y));
+    cairo_line_to(m_cairo,LogicalToDeviceX(x + rad),LogicalToDeviceY(y));
+    cairo_close_path(m_cairo);
+
+    SetBrush(m_brush);
+    cairo_fill_preserve(m_cairo);
+
+    SetPen(m_pen);
+    cairo_stroke(m_cairo);
+
+    CalcBoundingBox(x,y);
+    CalcBoundingBox(x+width,y+height);
+}
+
+void wxGtkPrintDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
+{
+    cairo_save (m_cairo);
+
+    cairo_translate (m_cairo, LogicalToDeviceX((wxCoord) (x + width / 2.)), LogicalToDeviceY((wxCoord) (y + height / 2.)));
+    cairo_scale(m_cairo, 1, (double)LogicalToDeviceYRel(height)/(double)LogicalToDeviceXRel(width));
+    cairo_arc ( m_cairo, 0, 0, LogicalToDeviceXRel(width/2), 0, 2 * M_PI);
+
+    SetBrush( m_brush );
+    cairo_fill_preserve( m_cairo );
+
+    SetPen (m_pen);
+    cairo_stroke( m_cairo );
+
+    CalcBoundingBox( x, y );
+    CalcBoundingBox( x + width, y + height );
+
+    cairo_restore (m_cairo);
+}
+
+#if wxUSE_SPLINES
+void wxGtkPrintDC::DoDrawSpline(wxList *points)
+{
+    SetPen (m_pen);
+
+    double c, d, x1, y1, x2, y2, x3, y3;
+    wxPoint *p, *q;
+
+    wxList::compatibility_iterator node = points->GetFirst();
+    p = (wxPoint *)node->GetData();
+    x1 = p->x;
+    y1 = p->y;
+
+    node = node->GetNext();
+    p = (wxPoint *)node->GetData();
+    c = p->x;
+    d = p->y;
+    x3 =
+         (double)(x1 + c) / 2;
+    y3 =
+         (double)(y1 + d) / 2;
+
+    cairo_new_path( m_cairo );
+    cairo_move_to( m_cairo, LogicalToDeviceX((wxCoord)x1), LogicalToDeviceY((wxCoord)y1) );
+    cairo_line_to( m_cairo, LogicalToDeviceX((wxCoord)x3), LogicalToDeviceY((wxCoord)y3) );
+
+    CalcBoundingBox( (wxCoord)x1, (wxCoord)y1 );
+    CalcBoundingBox( (wxCoord)x3, (wxCoord)y3 );
+
+    node = node->GetNext();
+    while (node)
+    {
+        q = (wxPoint *)node->GetData();
+
+        x1 = x3;
+        y1 = y3;
+        x2 = c;
+        y2 = d;
+        c = q->x;
+        d = q->y;
+        x3 = (double)(x2 + c) / 2;
+        y3 = (double)(y2 + d) / 2;
+
+        cairo_curve_to(m_cairo,
+            LogicalToDeviceX((wxCoord)x1), LogicalToDeviceY((wxCoord)y1),
+            LogicalToDeviceX((wxCoord)x2), LogicalToDeviceY((wxCoord)y2),
+            LogicalToDeviceX((wxCoord)x3), LogicalToDeviceY((wxCoord)y3) );
+
+        CalcBoundingBox( (wxCoord)x1, (wxCoord)y1 );
+        CalcBoundingBox( (wxCoord)x3, (wxCoord)y3 );
+
+        node = node->GetNext();
+    }
+
+    cairo_line_to ( m_cairo, LogicalToDeviceX((wxCoord)c), LogicalToDeviceY((wxCoord)d) );
+
+    cairo_stroke( m_cairo );
+}
+#endif // wxUSE_SPLINES
+
+bool wxGtkPrintDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
+            wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask,
+            wxCoord xsrcMask, wxCoord ysrcMask)
+{
+    wxCHECK_MSG( source, false, wxT("invalid source dc") );
+
+    // Blit into a bitmap.
+    wxBitmap bitmap( width, height );
+    wxMemoryDC memDC;
+    memDC.SelectObject(bitmap);
+    memDC.Blit(0, 0, width, height, source, xsrc, ysrc, rop);
+    memDC.SelectObject(wxNullBitmap);
+
+    // Draw bitmap. scaling and positioning is done there.
+    DrawBitmap( bitmap, xdest, ydest, useMask );
+
+    return true;
+}
+
+void wxGtkPrintDC::DoDrawIcon( const wxIcon& icon, wxCoord x, wxCoord y )
+{
+    DoDrawBitmap( icon, x, y, true );
+}
+
+void wxGtkPrintDC::DoDrawBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y, bool useMask )
+{
+    wxCHECK_RET( bitmap.IsOk(), wxT("Invalid bitmap in wxGtkPrintDC::DoDrawBitmap"));
+
+    cairo_surface_t* surface;
+    x = LogicalToDeviceX(x);
+    y = LogicalToDeviceY(y);
+    int bw = bitmap.GetWidth();
+    int bh = bitmap.GetHeight();
+    wxBitmap bmpSource = bitmap;  // we need a non-const instance.
+    unsigned char* buffer = new unsigned char[bw*bh*4];
+    wxUint32* data = (wxUint32*)buffer;
+
+    wxMask *mask = NULL;
+    if (useMask) mask = bmpSource.GetMask();
+
+    // Create a surface object and copy the bitmap pixel data to it. If the image has alpha (or a mask represented as alpha)
+    // then we'll use a different format and iterator than if it doesn't.
+    if (bmpSource.HasAlpha() || mask)
+    {
+        surface = cairo_image_surface_create_for_data(
+            buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4);
+        wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
+        wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
+
+        wxAlphaPixelData::Iterator p(pixData);
+        int y, x;
+        for (y=0; y<bh; y++)
+        {
+            wxAlphaPixelData::Iterator rowStart = p;
+            for (x=0; x<bw; x++)
+            {
+                // Each pixel in CAIRO_FORMAT_ARGB32 is a 32-bit quantity,
+                // with alpha in the upper 8 bits, then red, then green, then
+                // blue. The 32-bit quantities are stored native-endian.
+                // Pre-multiplied alpha is used.
+                unsigned char alpha = p.Alpha();
+                if (alpha == 0)
+                    *data = 0;
+                else
+                    *data = ( alpha/255                  << 24
+                              | (p.Red() * alpha/255)    << 16
+                              | (p.Green() * alpha/255)  <<  8
+                              | (p.Blue() * alpha/255) );
+                ++data;
+                ++p;
+            }
+            p = rowStart;
+            p.OffsetY(pixData, 1);
+        }
+    }
+    else  // no alpha
+    {
+        surface = cairo_image_surface_create_for_data(
+            buffer, CAIRO_FORMAT_RGB24, bw, bh, bw*4);
+        wxNativePixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
+        wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
+
+        wxNativePixelData::Iterator p(pixData);
+        int y, x;
+        for (y=0; y<bh; y++)
+        {
+            wxNativePixelData::Iterator rowStart = p;
+            for (x=0; x<bw; x++)
+            {
+                // Each pixel in CAIRO_FORMAT_RGB24 is a 32-bit quantity, with
+                // the upper 8 bits unused. Red, Green, and Blue are stored in
+                // the remaining 24 bits in that order.  The 32-bit quantities
+                // are stored native-endian.
+                *data = ( p.Red() << 16 | p.Green() << 8 | p.Blue() );
+                ++data;
+                ++p;
+            }
+            p = rowStart;
+            p.OffsetY(pixData, 1);
+        }
+    }
+
+
+    cairo_save(m_cairo);
+    // In case we're scaling the image by using a width and height different
+    // than the bitmap's size create a pattern transformation on the surface and
+    // draw the transformed pattern.
+    cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
+
+    // Prepare to draw the image.
+    cairo_translate(m_cairo, x, y);
+    cairo_set_source(m_cairo, pattern);
+    // Use the original size here since the context is scaled already.
+    cairo_rectangle(m_cairo, 0, 0, bw, bh);
+    // Fill the rectangle using the pattern.
+    cairo_fill(m_cairo);
+
+    // Clean up.
+    cairo_pattern_destroy(pattern);
+    cairo_surface_destroy(surface);
+    delete [] buffer;
+
+    CalcBoundingBox(0,0);
+    CalcBoundingBox(bw,bh);
+
+    cairo_restore(m_cairo);
+}
+
+// wxGtkPrintDC has a constant resolution of 72dpi. If we want an higher resolution for printing
+// an image, the scaling has to be done by cairo.
+void wxGtkPrintDC::DoDrawScaledBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y, wxCoord w, wxCoord h, bool useMask, int quality )
+{
+    wxCHECK_RET( bitmap.IsOk(), wxT("Invalid bitmap in wxGtkPrintDC::DoDrawBitmap"));
+
+    cairo_surface_t* surface;
+    int bw = bitmap.GetWidth();
+    int bh = bitmap.GetHeight();
+    x = LogicalToDeviceX(x);
+    y = LogicalToDeviceY(y);
+    w = LogicalToDeviceXRel(w);
+    h = LogicalToDeviceYRel(h);
+    wxBitmap bmpSource = bitmap;  // we need a non-const instance.
+    unsigned char* buffer = new unsigned char[bw*bh*4];
+    wxUint32* data = (wxUint32*)buffer;
+
+    // Create a surface object and copy the bitmap pixel data to it. If the image has alpha (or a mask represented as alpha)
+    // then we'll use a different format and iterator than if it doesn't.
+    if (bmpSource.HasAlpha() || bmpSource.GetMask())
+    {
+        surface = cairo_image_surface_create_for_data(
+            buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4);
+        wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
+        wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
+
+        wxAlphaPixelData::Iterator p(pixData);
+        int y, x;
+        for (y=0; y<bh; y++)
+        {
+            wxAlphaPixelData::Iterator rowStart = p;
+            for (x=0; x<bw; x++)
+            {
+                // Each pixel in CAIRO_FORMAT_ARGB32 is a 32-bit quantity,
+                // with alpha in the upper 8 bits, then red, then green, then
+                // blue. The 32-bit quantities are stored native-endian.
+                // Pre-multiplied alpha is used.
+                unsigned char alpha = p.Alpha();
+                if (alpha == 0)
+                    *data = 0;
+                else
+                    *data = ( alpha                  << 24
+                              | (p.Red() * alpha/255)    << 16
+                              | (p.Green() * alpha/255)  <<  8
+                              | (p.Blue() * alpha/255) );
+                ++data;
+                ++p;
+            }
+            p = rowStart;
+            p.OffsetY(pixData, 1);
+        }
+    }
+    else  // no alpha
+    {
+        surface = cairo_image_surface_create_for_data(
+            buffer, CAIRO_FORMAT_RGB24, bw, bh, bw*4);
+        wxNativePixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
+        wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
+
+        wxNativePixelData::Iterator p(pixData);
+        int y, x;
+        for (y=0; y<bh; y++)
+        {
+            wxNativePixelData::Iterator rowStart = p;
+            for (x=0; x<bw; x++)
+            {
+                // Each pixel in CAIRO_FORMAT_RGB24 is a 32-bit quantity, with
+                // the upper 8 bits unused. Red, Green, and Blue are stored in
+                // the remaining 24 bits in that order.  The 32-bit quantities
+                // are stored native-endian.
+                *data = ( p.Red() << 16 | p.Green() << 8 | p.Blue() );
+                ++data;
+                ++p;
+            }
+            p = rowStart;
+            p.OffsetY(pixData, 1);
+        }
+    }
+
+
+    cairo_save(m_cairo);
+
+    // Prepare to draw the image.
+    cairo_translate(m_cairo, x, y);
+
+    // In case we're scaling the image by using a width and height different
+    // than the bitmap's size create a pattern transformation on the surface and
+    // draw the transformed pattern.
+    cairo_filter_t filter;
+    if (quality == wxIMAGE_QUALITY_HIGH) filter = CAIRO_FILTER_BILINEAR;
+    else filter = CAIRO_FILTER_GOOD;
+    cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
+    cairo_pattern_set_filter(pattern,filter);
+    wxDouble scaleX = (wxDouble) w / (wxDouble) bw;
+    wxDouble scaleY = (wxDouble) h / (wxDouble) bh;
+    cairo_scale(m_cairo, scaleX, scaleY);
+
+    cairo_set_source(m_cairo, pattern);
+    // Use the original size here since the context is scaled already.
+    cairo_rectangle(m_cairo, 0, 0, bw, bh);
+    // Fill the rectangle using the pattern.
+    cairo_fill(m_cairo);
+
+    // Clean up.
+    cairo_pattern_destroy(pattern);
+    cairo_surface_destroy(surface);
+    delete [] buffer;
+
+    CalcBoundingBox(0,0);
+    CalcBoundingBox(bw,bh);
+
+    cairo_restore(m_cairo);
+}
+
+void wxGtkPrintDC::DoDrawText(const wxString& text, wxCoord x, wxCoord y )
+{
+    DoDrawRotatedText( text, x, y, 0.0 );
+}
+
+void wxGtkPrintDC::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle)
+{
+    x = LogicalToDeviceX(x);
+    y = LogicalToDeviceY(y);
+
+    angle = -angle;
+
+    bool underlined = m_font.Ok() && m_font.GetUnderlined();
+
+// FIXME-UTF8: wouldn't be needed if utf8_str() always returned a buffer
+#if wxUSE_UNICODE_UTF8
+    const char *data = text.utf8_str();
+#else
+    const wxCharBuffer data = text.utf8_str();
+#endif
+
+    size_t datalen = strlen(data);
+    pango_layout_set_text( m_layout, data, datalen);
+
+    if (underlined)
+    {
+        PangoAttrList *attrs = pango_attr_list_new();
+        PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
+        a->start_index = 0;
+        a->end_index = datalen;
+        pango_attr_list_insert(attrs, a);
+        pango_layout_set_attributes(m_layout, attrs);
+        pango_attr_list_unref(attrs);
+    }
+
+    if (m_textForegroundColour.Ok())
+    {
+        unsigned char red = m_textForegroundColour.Red();
+        unsigned char blue = m_textForegroundColour.Blue();
+        unsigned char green = m_textForegroundColour.Green();
+        unsigned char alpha = m_textForegroundColour.Alpha();
+
+        if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue && alpha == m_currentAlpha))
+        {
+            double redPS = (double)(red) / 255.0;
+            double bluePS = (double)(blue) / 255.0;
+            double greenPS = (double)(green) / 255.0;
+            double alphaPS = (double)(alpha) / 255.0;
+
+            cairo_set_source_rgba( m_cairo, redPS, greenPS, bluePS, alphaPS );
+
+            m_currentRed = red;
+            m_currentBlue = blue;
+            m_currentGreen = green;
+            m_currentAlpha = alpha;
+        }
+    }
+
+    int w,h;
+
+    if (fabs(m_scaleY - 1.0) > 0.00001)
+    {
+        // If there is a user or actually any scale applied to the device context, scale the font.
+
+        // Scale font description.
+        gint oldSize = pango_font_description_get_size( m_fontdesc );
+        double size = oldSize;
+        size = size * m_scaleY;
+        pango_font_description_set_size( m_fontdesc, (gint)size );
+
+        // Actually apply scaled font.
+        pango_layout_set_font_description( m_layout, m_fontdesc );
+
+        pango_layout_get_pixel_size( m_layout, &w, &h );
+        w = LogicalToDeviceXRel(w);
+        h = LogicalToDeviceYRel(h);
+
+        if ( m_backgroundMode == wxSOLID )
+        {
+            unsigned char red = m_textBackgroundColour.Red();
+            unsigned char blue = m_textBackgroundColour.Blue();
+            unsigned char green = m_textBackgroundColour.Green();
+            unsigned char alpha = m_textBackgroundColour.Alpha();
+
+            double redPS = (double)(red) / 255.0;
+            double bluePS = (double)(blue) / 255.0;
+            double greenPS = (double)(green) / 255.0;
+            double alphaPS = (double)(alpha) / 255.0;
+
+            cairo_save(m_cairo);
+            cairo_translate(m_cairo, x, y);
+            cairo_set_source_rgba( m_cairo, redPS, greenPS, bluePS, alphaPS );
+            cairo_rotate(m_cairo,angle*DEG2RAD);
+            cairo_rectangle(m_cairo, 0, 0, w, h);
+            cairo_fill(m_cairo);
+            cairo_restore(m_cairo);
+        }
+
+        // Draw layout.
+        cairo_move_to (m_cairo, x, y);
+        if (fabs(angle) > 0.00001)
+        {
+            cairo_save( m_cairo );
+            cairo_rotate( m_cairo, angle*DEG2RAD );
+            pango_cairo_update_layout (m_cairo, m_layout);
+            pango_cairo_show_layout (m_cairo, m_layout);
+            cairo_restore( m_cairo );
+        }
+        else
+        {
+            pango_cairo_update_layout (m_cairo, m_layout);
+            pango_cairo_show_layout (m_cairo, m_layout);
+        }
+
+        // Reset unscaled size.
+        pango_font_description_set_size( m_fontdesc, oldSize );
+
+        // Actually apply unscaled font.
+        pango_layout_set_font_description( m_layout, m_fontdesc );
+    }
+    else
+    {
+        pango_layout_get_pixel_size( m_layout, &w, &h );
+
+        if ( m_backgroundMode == wxSOLID )
+        {
+            unsigned char red = m_textBackgroundColour.Red();
+            unsigned char blue = m_textBackgroundColour.Blue();
+            unsigned char green = m_textBackgroundColour.Green();
+            unsigned char alpha = m_textBackgroundColour.Alpha();
+
+            double redPS = (double)(red) / 255.0;
+            double bluePS = (double)(blue) / 255.0;
+            double greenPS = (double)(green) / 255.0;
+            double alphaPS = (double)(alpha) / 255.0;
+
+            cairo_save(m_cairo);
+            cairo_translate(m_cairo, x, y);
+            cairo_set_source_rgba( m_cairo, redPS, greenPS, bluePS, alphaPS );
+            cairo_rotate(m_cairo,angle*DEG2RAD);
+            cairo_rectangle(m_cairo, 0, 0, w, h);
+            cairo_fill(m_cairo);
+            cairo_restore(m_cairo);
+        }
+
+        // Draw layout.
+        cairo_move_to (m_cairo, x, y);
+        if (fabs(angle) > 0.00001)
+        {
+            cairo_save( m_cairo );
+            cairo_rotate( m_cairo, angle*DEG2RAD );
+            pango_cairo_update_layout (m_cairo, m_layout);
+            pango_cairo_show_layout (m_cairo, m_layout);
+            cairo_restore( m_cairo );
+        }
+        else
+        {
+            pango_cairo_update_layout (m_cairo, m_layout);
+            pango_cairo_show_layout (m_cairo, m_layout);
+        }
+    }
+
+    if (underlined)
+    {
+        // Undo underline attributes setting
+        pango_layout_set_attributes(m_layout, NULL);
+    }
+
+    CalcBoundingBox (x,y);
+    CalcBoundingBox (x + w, y + h);
+}
+
+void wxGtkPrintDC::Clear()
+{
+    cairo_save(m_cairo);
+    cairo_set_operator (m_cairo, CAIRO_OPERATOR_SOURCE);
+    SetBrush(m_backgroundBrush);
+    cairo_paint(m_cairo);
+    cairo_restore(m_cairo);
+}
+
+void wxGtkPrintDC::SetFont( const wxFont& font )
+{
+    m_font = font;
+
+    if (m_font.Ok())
+    {
+        if (m_fontdesc)
+            pango_font_description_free( m_fontdesc );
+
+        m_fontdesc = pango_font_description_copy( m_font.GetNativeFontInfo()->description );
+
+        pango_layout_set_font_description( m_layout, m_fontdesc );
+    }
+}
+
+void wxGtkPrintDC::SetPen( const wxPen& pen )
+{
+    if (!pen.Ok()) return;
+
+    m_pen = pen;
+
+    double width = (double) m_pen.GetWidth();
+    if (width == 0) width = 0.1;
+
+    cairo_set_line_width( m_cairo, LogicalToDeviceXRel( (wxCoord) (1000 * width )) / 1000.0f );
+    static const double dotted[] = {2.0, 5.0};
+    static const double short_dashed[] = {4.0, 4.0};
+    static const double long_dashed[] = {4.0, 8.0};
+    static const double dotted_dashed[] = {6.0, 6.0, 2.0, 6.0};
+
+    switch (m_pen.GetStyle())
+    {
+        case wxDOT:           cairo_set_dash( m_cairo, dotted, 1, 0 ); break;
+        case wxSHORT_DASH:    cairo_set_dash( m_cairo, short_dashed, 1, 0 ); break;
+        case wxLONG_DASH:     cairo_set_dash( m_cairo, long_dashed, 1, 0 ); break;
+        case wxDOT_DASH:      cairo_set_dash( m_cairo, dotted_dashed, 3, 0 );  break;
+        case wxUSER_DASH:
+        {
+            wxDash *wx_dashes;
+            int num = m_pen.GetDashes (&wx_dashes) - 1;
+            gdouble *g_dashes = g_new( gdouble, num );
+            int i;
+            for (i = 0; i < num; ++i)
+                g_dashes[i] = (gdouble) wx_dashes[i];
+            cairo_set_dash( m_cairo, g_dashes, num, 0);
+            g_free( g_dashes );
+        }
+        break;
+        case wxSOLID:
+        case wxTRANSPARENT:
+        default:              cairo_set_dash( m_cairo, NULL, 0, 0 );   break;
+    }
+
+    switch (m_pen.GetCap())
+    {
+        case wxCAP_PROJECTING:  cairo_set_line_cap (m_cairo, CAIRO_LINE_CAP_SQUARE); break;
+        case wxCAP_BUTT:        cairo_set_line_cap (m_cairo, CAIRO_LINE_CAP_BUTT); break;
+        case wxCAP_ROUND:
+        default:                cairo_set_line_cap (m_cairo, CAIRO_LINE_CAP_ROUND); break;
+    }
+
+    switch (m_pen.GetJoin())
+    {
+        case wxJOIN_BEVEL:  cairo_set_line_join (m_cairo, CAIRO_LINE_JOIN_BEVEL); break;
+        case wxJOIN_MITER:  cairo_set_line_join (m_cairo, CAIRO_LINE_JOIN_MITER); break;
+        case wxJOIN_ROUND:
+        default:            cairo_set_line_join (m_cairo, CAIRO_LINE_JOIN_ROUND); break;
+    }
+
+    unsigned char red = m_pen.GetColour().Red();
+    unsigned char blue = m_pen.GetColour().Blue();
+    unsigned char green = m_pen.GetColour().Green();
+    unsigned char alpha = m_pen.GetColour().Alpha();
+
+    if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue && alpha == m_currentAlpha))
+    {
+        double redPS = (double)(red) / 255.0;
+        double bluePS = (double)(blue) / 255.0;
+        double greenPS = (double)(green) / 255.0;
+        double alphaPS = (double)(alpha) / 255.0;
+
+        cairo_set_source_rgba( m_cairo, redPS, greenPS, bluePS, alphaPS );
+
+        m_currentRed = red;
+        m_currentBlue = blue;
+        m_currentGreen = green;
+        m_currentAlpha = alpha;
+    }
+}
+
+void wxGtkPrintDC::SetBrush( const wxBrush& brush )
+{
+    if (!brush.Ok()) return;
+
+    m_brush = brush;
+
+    // Brush colour.
+    unsigned char red = m_brush.GetColour().Red();
+    unsigned char blue = m_brush.GetColour().Blue();
+    unsigned char green = m_brush.GetColour().Green();
+    unsigned char alpha = m_brush.GetColour().Alpha();
+
+    double redPS = (double)(red) / 255.0;
+    double bluePS = (double)(blue) / 255.0;
+    double greenPS = (double)(green) / 255.0;
+    double alphaPS = (double)(alpha) / 255.0;
+
+    if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue && alpha == m_currentAlpha))
+    {
+        cairo_set_source_rgba( m_cairo, redPS, greenPS, bluePS, alphaPS );
+
+        m_currentRed = red;
+        m_currentBlue = blue;
+        m_currentGreen = green;
+        m_currentAlpha = alpha;
+    }
+
+    if (m_brush.IsHatch())
+    {
+        cairo_t * cr;
+        cairo_surface_t *surface;
+        surface = cairo_surface_create_similar(cairo_get_target(m_cairo),CAIRO_CONTENT_COLOR_ALPHA,10,10);
+        cr = cairo_create(surface);
+        cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
+        cairo_set_line_width(cr, 1);
+        cairo_set_line_join(cr,CAIRO_LINE_JOIN_MITER);
+
+        switch (m_brush.GetStyle())
+        {
+            case wxCROSS_HATCH:
+                cairo_move_to(cr, 5, 0);
+                cairo_line_to(cr, 5, 10);
+                cairo_move_to(cr, 0, 5);
+                cairo_line_to(cr, 10, 5);
+                break;
+            case wxBDIAGONAL_HATCH:
+                cairo_move_to(cr, 0, 10);
+                cairo_line_to(cr, 10, 0);
+                break;
+            case wxFDIAGONAL_HATCH:
+                cairo_move_to(cr, 0, 0);
+                cairo_line_to(cr, 10, 10);
+                break;
+            case wxCROSSDIAG_HATCH:
+                cairo_move_to(cr, 0, 0);
+                cairo_line_to(cr, 10, 10);
+                cairo_move_to(cr, 10, 0);
+                cairo_line_to(cr, 0, 10);
+                break;
+            case wxHORIZONTAL_HATCH:
+                cairo_move_to(cr, 0, 5);
+                cairo_line_to(cr, 10, 5);
+                break;
+            case wxVERTICAL_HATCH:
+                cairo_move_to(cr, 5, 0);
+                cairo_line_to(cr, 5, 10);
+                break;
+            default:
+                wxFAIL_MSG(_("Couldn't get hatch style from wxBrush."));
+        }
+
+        cairo_set_source_rgba(cr, redPS, greenPS, bluePS, alphaPS);
+        cairo_stroke (cr);
+
+        cairo_destroy(cr);
+        cairo_pattern_t * pattern = cairo_pattern_create_for_surface (surface);
+        cairo_surface_destroy(surface);
+        cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+        cairo_set_source(m_cairo, pattern);
+        cairo_pattern_destroy(pattern);
+    }
+}
+
+void wxGtkPrintDC::SetLogicalFunction( int function )
+{
+    if (function == wxCLEAR)
+        cairo_set_operator (m_cairo, CAIRO_OPERATOR_CLEAR);
+    else if (function == wxOR)
+        cairo_set_operator (m_cairo, CAIRO_OPERATOR_OUT);
+    else if (function == wxNO_OP)
+        cairo_set_operator (m_cairo, CAIRO_OPERATOR_DEST);
+    else if (function == wxAND)
+        cairo_set_operator (m_cairo, CAIRO_OPERATOR_ADD);
+    else if (function == wxSET)
+        cairo_set_operator (m_cairo, CAIRO_OPERATOR_SATURATE);
+    else if (function == wxXOR)
+        cairo_set_operator (m_cairo, CAIRO_OPERATOR_XOR);
+    else // wxCOPY or anything else.
+        cairo_set_operator (m_cairo, CAIRO_OPERATOR_SOURCE);
+}
+
+void wxGtkPrintDC::SetBackground( const wxBrush& brush )
+{
+    m_backgroundBrush = brush;
+    cairo_save(m_cairo);
+    cairo_set_operator (m_cairo, CAIRO_OPERATOR_DEST_OVER);
+
+    SetBrush(m_backgroundBrush);
+    cairo_paint(m_cairo);
+    cairo_restore(m_cairo);
+}
+
+void wxGtkPrintDC::SetBackgroundMode(int mode)
+{
+    if (mode == wxSOLID) m_backgroundMode = wxSOLID;
+    else m_backgroundMode = wxTRANSPARENT;
+}
+
+void wxGtkPrintDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
+{
+    cairo_rectangle ( m_cairo, LogicalToDeviceX(x), LogicalToDeviceY(y), LogicalToDeviceXRel(width), LogicalToDeviceYRel(height));
+    cairo_clip(m_cairo);
+}
+
+void wxGtkPrintDC::DestroyClippingRegion()
+{
+    cairo_reset_clip(m_cairo);
+}
+
+bool wxGtkPrintDC::StartDoc(const wxString& message)
+{
+    return true;
+}
+
+void wxGtkPrintDC::EndDoc()
+{
+    return;
+}
+
+void wxGtkPrintDC::StartPage()
+{
+    return;
+}
+
+void wxGtkPrintDC::EndPage()
+{
+    return;
+}
+
+wxCoord wxGtkPrintDC::GetCharHeight() const
+{
+    pango_layout_set_text( m_layout, "H", 1 );
+
+    int w,h;
+    pango_layout_get_pixel_size( m_layout, &w, &h );
+
+    return DeviceToLogicalYRel(h);
+}
+
+wxCoord wxGtkPrintDC::GetCharWidth() const
+{
+    pango_layout_set_text( m_layout, "H", 1 );
+
+    int w,h;
+    pango_layout_get_pixel_size( m_layout, &w, &h );
+
+    return DeviceToLogicalXRel(w);
+}
+
+void wxGtkPrintDC::DoGetTextExtent(const wxString& string, wxCoord *width, wxCoord *height,
+                     wxCoord *descent,
+                     wxCoord *externalLeading,
+                     const wxFont *theFont ) const
+{
+    if ( width )
+        *width = 0;
+    if ( height )
+        *height = 0;
+    if ( descent )
+        *descent = 0;
+    if ( externalLeading )
+        *externalLeading = 0;
+
+    if (string.empty())
+    {
+        return;
+    }
+
+    // Set layout's text
+    // FIXME-UTF8: wouldn't be needed if utf8_str() always returned a buffer
+#if wxUSE_UNICODE_UTF8
+    const char *dataUTF8 = string.utf8_str();
+#else
+    const wxCharBuffer dataUTF8 = string.utf8_str();
+#endif
+
+    PangoFontDescription *desc = m_fontdesc;
+    if (theFont) desc = theFont->GetNativeFontInfo()->description;
+
+    gint oldSize = pango_font_description_get_size( desc );
+    double size = oldSize;
+    size = size * m_scaleY;
+    pango_font_description_set_size( desc, (gint)size );
+
+    // apply scaled font
+    pango_layout_set_font_description( m_layout, desc );
+
+    pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) );
+
+    int w, h;
+    pango_layout_get_pixel_size( m_layout, &w, &h );
+
+    if (width)
+        *width = (wxCoord)(w / m_scaleX);
+    if (height)
+        *height = (wxCoord)(h / m_scaleY);
+    if (descent)
+    {
+        PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
+        int baseline = pango_layout_iter_get_baseline(iter);
+        pango_layout_iter_free(iter);
+        *descent = h - PANGO_PIXELS(baseline);
+    }
+
+    // Reset unscaled size.
+    pango_font_description_set_size( desc, oldSize );
+
+    // Reset unscaled font.
+    pango_layout_set_font_description( m_layout, m_fontdesc );
+}
+
+void wxGtkPrintDC::DoGetSize(int* width, int* height) const
+{
+    if (width)
+        *width = (int) (gtk_print_context_get_width( m_gpc ) + 0.5);
+    if (height)
+        *height = (int) (gtk_print_context_get_height( m_gpc ) + 0.5);
+}
+
+void wxGtkPrintDC::DoGetSizeMM(int *width, int *height) const
+{
+    // This function takes margins into consideration.
+    gdouble w = gtk_page_setup_get_page_width( gtk_print_context_get_page_setup( m_gpc ), GTK_UNIT_MM);
+    gdouble h = gtk_page_setup_get_page_height( gtk_print_context_get_page_setup( m_gpc ), GTK_UNIT_MM);
+
+    if (width)
+        *width = (int) (w + 0.5);
+    if (height)
+        *height = (int) (h + 0.5);
+}
+
+wxSize wxGtkPrintDC::GetPPI() const
+{
+    gdouble xDpi = gtk_print_context_get_dpi_x( m_gpc );
+    gdouble yDpi = gtk_print_context_get_dpi_y( m_gpc );
+    return wxSize((int) xDpi,(int) yDpi);
+}
+
+void wxGtkPrintDC::SetLogicalOrigin( wxCoord x, wxCoord y )
+{
+    wxDC::SetLogicalOrigin( x, y );
+}
+
+void wxGtkPrintDC::SetDeviceOrigin( wxCoord x, wxCoord y )
+{
+    wxDC::SetDeviceOrigin( x, y );
+}
+
+void wxGtkPrintDC::SetPrintData(const wxPrintData& data)
+{
+    m_printData = data;
+
+    if (m_printData.GetOrientation() == wxPORTRAIT)
+        GetSize( &m_deviceOffsetX, &m_deviceOffsetY );
+    else
+        GetSize( &m_deviceOffsetY, &m_deviceOffsetX );
+}
+
+void wxGtkPrintDC::SetResolution(int ppi)
+{
+    // We can't change ppi of the GtkPrintContext.
+    ms_resolution = ppi;
+}
+
+int wxGtkPrintDC::GetResolution()
+{
+    return ms_resolution;
+}
+
+// ----------------------------------------------------------------------------
+// Print preview
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGtkPrintPreview, wxPrintPreviewBase)
+
+void wxGtkPrintPreview::Init(wxPrintout * WXUNUSED(printout),
+                                    wxPrintout * WXUNUSED(printoutForPrinting))
+{
+    DetermineScaling();
+}
+
+wxGtkPrintPreview::wxGtkPrintPreview(wxPrintout *printout,
+                                                   wxPrintout *printoutForPrinting,
+                                                   wxPrintDialogData *data)
+                        : wxPrintPreviewBase(printout, printoutForPrinting, data)
+{
+    Init(printout, printoutForPrinting);
+}
+
+wxGtkPrintPreview::wxGtkPrintPreview(wxPrintout *printout,
+                                                   wxPrintout *printoutForPrinting,
+                                                   wxPrintData *data)
+                        : wxPrintPreviewBase(printout, printoutForPrinting, data)
+{
+    Init(printout, printoutForPrinting);
+}
+
+wxGtkPrintPreview::~wxGtkPrintPreview()
+{
+}
+
+bool wxGtkPrintPreview::Print(bool interactive)
+{
+    if (!m_printPrintout)
+        return false;
+
+    wxPrinter printer(& m_printDialogData);
+    return printer.Print(m_previewFrame, m_printPrintout, interactive);
+}
+
+void wxGtkPrintPreview::DetermineScaling()
+{
+    wxPaperSize paperType = m_printDialogData.GetPrintData().GetPaperId();
+
+    wxPrintPaperType *paper = wxThePrintPaperDatabase->FindPaperType(paperType);
+    if (!paper)
+        paper = wxThePrintPaperDatabase->FindPaperType(wxPAPER_A4);
+
+    if (paper)
+    {
+        wxSize ScreenPixels = wxGetDisplaySize();
+        wxSize ScreenMM = wxGetDisplaySizeMM();
+
+        m_previewPrintout->SetPPIScreen( (int) ((ScreenPixels.GetWidth() * 25.4) / ScreenMM.GetWidth()),
+                                         (int) ((ScreenPixels.GetHeight() * 25.4) / ScreenMM.GetHeight()) );
+        m_previewPrintout->SetPPIPrinter(wxGtkPrintDC::GetResolution(), wxGtkPrintDC::GetResolution());
+        // Get width and height in points (1/72th of an inch)
+        wxSize sizeDevUnits(paper->GetSizeDeviceUnits());
+
+        sizeDevUnits.x = (wxCoord)((float)sizeDevUnits.x * wxGtkPrintDC::GetResolution() / 72.0);
+        sizeDevUnits.y = (wxCoord)((float)sizeDevUnits.y * wxGtkPrintDC::GetResolution() / 72.0);
+        wxSize sizeTenthsMM(paper->GetSize());
+        wxSize sizeMM(sizeTenthsMM.x / 10, sizeTenthsMM.y / 10);
+
+        // If in landscape mode, we need to swap the width and height.
+        if ( m_printDialogData.GetPrintData().GetOrientation() == wxLANDSCAPE )
+        {
+            m_pageWidth = sizeDevUnits.y;
+            m_pageHeight = sizeDevUnits.x;
+            m_previewPrintout->SetPageSizeMM(sizeMM.y, sizeMM.x);
+        }
+        else
+        {
+            m_pageWidth = sizeDevUnits.x;
+            m_pageHeight = sizeDevUnits.y;
+            m_previewPrintout->SetPageSizeMM(sizeMM.x, sizeMM.y);
+        }
+        m_previewPrintout->SetPageSizePixels(m_pageWidth, m_pageHeight);
+        m_previewPrintout->SetPaperRectPixels(wxRect(0, 0, m_pageWidth, m_pageHeight));
+
+        // At 100%, the page should look about page-size on the screen.
+        m_previewScaleX = (float)0.8 * 72.0 / (float)wxGtkPrintDC::GetResolution();
+        m_previewScaleY = m_previewScaleX;
+    }
+}
+
+#endif
+     // wxUSE_GTKPRINT