]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/dcpsg.cpp
fix DrawLine() and DrawPolygon() which were totally broken for GTK1 since rev 36998
[wxWidgets.git] / src / generic / dcpsg.cpp
index ff50f091200aae35f2bd34c6da71bbf97072b747..1af7e67852bdd5a61ed992a73f82dac695a31d2b 100644 (file)
     #pragma hdrstop
 #endif
 
-#ifndef WX_PRECOMP
-#endif // WX_PRECOMP
+#if wxUSE_PRINTING_ARCHITECTURE && wxUSE_POSTSCRIPT
 
-#if wxUSE_PRINTING_ARCHITECTURE
+#include "wx/generic/dcpsg.h"
 
-#if wxUSE_POSTSCRIPT
+#ifndef WX_PRECOMP
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/utils.h"
+    #include "wx/dcmemory.h"
+    #include "wx/math.h"
+    #include "wx/image.h"
+    #include "wx/icon.h"
+#endif // WX_PRECOMP
 
-#include "wx/dcmemory.h"
-#include "wx/utils.h"
-#include "wx/intl.h"
-#include "wx/app.h"
-#include "wx/image.h"
-#include "wx/log.h"
-#include "wx/generic/dcpsg.h"
 #include "wx/prntbase.h"
 #include "wx/generic/prntdlgg.h"
 #include "wx/paper.h"
 #include "wx/filefn.h"
-#include "wx/math.h"
 #include "wx/stdpaths.h"
 
 #ifdef __WXMSW__
@@ -236,22 +235,32 @@ static char wxPostScriptHeaderReencodeISO2[] =
 // wxPostScriptDC
 //-------------------------------------------------------------------------------
 
+// conversion
+static const double RAD2DEG  = 180.0 / M_PI;
+
+// we don't want to use only 72 dpi from PS print
+static const int DPI = 600;
+static const double PS2DEV = 600.0 / 72.0;
+static const double DEV2PS = 72.0 / 600.0;
+
+#define XLOG2DEV(x)     ((double)(LogicalToDeviceX(x)) * DEV2PS)
+#define XLOG2DEVREL(x)  ((double)(LogicalToDeviceXRel(x)) * DEV2PS)
+#define YLOG2DEV(x)     ((m_pageHeight - (double)LogicalToDeviceY(x)) * DEV2PS)
+#define YLOG2DEVREL(x)  ((double)(LogicalToDeviceYRel(x)) * DEV2PS)
+
 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptDC, wxDC)
 
-float wxPostScriptDC::ms_PSScaleFactor = 1.0;
+//-------------------------------------------------------------------------------
 
 void wxPostScriptDC::SetResolution(int ppi)
 {
-    ms_PSScaleFactor = (float)ppi / 72.0;
 }
 
 int wxPostScriptDC::GetResolution()
 {
-    return (int)(ms_PSScaleFactor * 72.0);
+    return DPI;
 }
 
-//-------------------------------------------------------------------------------
-
 wxPostScriptDC::wxPostScriptDC ()
 {
     m_pstream = (FILE*) NULL;
@@ -267,8 +276,7 @@ wxPostScriptDC::wxPostScriptDC ()
     m_underlinePosition = 0.0;
     m_underlineThickness = 0.0;
 
-    m_signX =  1;  // default x-axis left to right
-    m_signY = -1;  // default y-axis bottom up -> top down
+    m_pageHeight = 842 * PS2DEV;
 }
 
 wxPostScriptDC::wxPostScriptDC (const wxPrintData& printData)
@@ -286,10 +294,9 @@ wxPostScriptDC::wxPostScriptDC (const wxPrintData& printData)
     m_underlinePosition = 0.0;
     m_underlineThickness = 0.0;
 
-    m_signX =  1;  // default x-axis left to right
-    m_signY = -1;  // default y-axis bottom up -> top down
-
-    m_printData = printData;
+    // this calculates m_pageHeight required for
+    // taking the inverted Y axis into account
+    SetPrintData( printData );
 
     m_ok = true;
 }
@@ -303,7 +310,7 @@ wxPostScriptDC::~wxPostScriptDC ()
     }
 }
 
-bool wxPostScriptDC::Ok() const
+bool wxPostScriptDC::IsOk() const
 {
   return m_ok;
 }
@@ -318,16 +325,20 @@ void wxPostScriptDC::DoSetClippingRegion (wxCoord x, wxCoord y, wxCoord w, wxCoo
 
     m_clipping = true;
 
-    PsPrintf( wxT("gsave\n newpath\n")
-              wxT("%d %d moveto\n")
-              wxT("%d %d lineto\n")
-              wxT("%d %d lineto\n")
-              wxT("%d %d lineto\n")
-              wxT("closepath clip newpath\n"),
-            LogicalToDeviceX(x),   LogicalToDeviceY(y),
-            LogicalToDeviceX(x+w), LogicalToDeviceY(y),
-            LogicalToDeviceX(x+w), LogicalToDeviceY(y+h),
-            LogicalToDeviceX(x),   LogicalToDeviceY(y+h) );
+    wxString buffer;
+    buffer.Printf( "gsave\n"
+                   "newpath\n"
+                   "%f %f moveto\n"
+                   "%f %f lineto\n"
+                   "%f %f lineto\n"
+                   "%f %f lineto\n"
+                   "closepath clip newpath\n",
+            XLOG2DEV(x),   YLOG2DEV(y),
+            XLOG2DEV(x+w), YLOG2DEV(y),
+            XLOG2DEV(x+w), YLOG2DEV(y+h),
+            XLOG2DEV(x),   YLOG2DEV(y+h) );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 }
 
 
@@ -376,26 +387,27 @@ void wxPostScriptDC::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
 
     SetPen( m_pen );
 
-    PsPrintf( wxT("newpath\n")
-              wxT("%d %d moveto\n")
-              wxT("%d %d lineto\n")
-              wxT("stroke\n"),
-            LogicalToDeviceX(x1), LogicalToDeviceY(y1),
-            LogicalToDeviceX(x2), LogicalToDeviceY (y2) );
+    wxString buffer;
+    buffer.Printf( "newpath\n"
+                   "%f %f moveto\n"
+                   "%f %f lineto\n"
+                   "stroke\n",
+            XLOG2DEV(x1), YLOG2DEV(y1),
+            XLOG2DEV(x2), YLOG2DEV(y2) );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 
     CalcBoundingBox( x1, y1 );
     CalcBoundingBox( x2, y2 );
 }
 
-#define RAD2DEG 57.29577951308
-
 void wxPostScriptDC::DoDrawArc (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
 {
     wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
 
     wxCoord dx = x1 - xc;
     wxCoord dy = y1 - yc;
-    wxCoord radius = (wxCoord) sqrt( (double)(dx*dx+dy*dy) );
+    double radius = sqrt( (double)(dx*dx+dy*dy) );
     double alpha1, alpha2;
 
     if (x1 == x2 && y1 == y2)
@@ -422,36 +434,48 @@ void wxPostScriptDC::DoDrawArc (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
     while (alpha1 > 360)  alpha1 -= 360; // 0 and 360 degree
     while (alpha2 > 360)  alpha2 -= 360;
 
+    int i_radius = wxRound( radius );
+
     if (m_brush.GetStyle() != wxTRANSPARENT)
     {
         SetBrush( m_brush );
 
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d %d %d %d %d ellipse\n")
-                  wxT("%d %d lineto\n")
-                  wxT("closepath\n")
-                  wxT("fill\n"),
-                LogicalToDeviceX(xc), LogicalToDeviceY(yc), LogicalToDeviceXRel(radius), LogicalToDeviceYRel(radius), (wxCoord)alpha1, (wxCoord) alpha2,
-                LogicalToDeviceX(xc), LogicalToDeviceY(yc) );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f %f %f %f %f ellipse\n"
+                       "%f %f lineto\n"
+                       "closepath\n"
+                       "fill\n",
+                XLOG2DEV(xc), YLOG2DEV(yc),
+                XLOG2DEVREL(i_radius), YLOG2DEVREL(i_radius),
+                alpha1, alpha2,
+                XLOG2DEV(xc), YLOG2DEV(yc) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
-        CalcBoundingBox( xc-radius, yc-radius );
-        CalcBoundingBox( xc+radius, yc+radius );
+        CalcBoundingBox( xc-i_radius, yc-i_radius );
+        CalcBoundingBox( xc+i_radius, yc+i_radius );
     }
 
     if (m_pen.GetStyle() != wxTRANSPARENT)
     {
         SetPen( m_pen );
 
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d %d %d %d %d ellipse\n")
-                  wxT("%d %d lineto\n")
-                  wxT("stroke\n")
-                  wxT("fill\n"),
-                LogicalToDeviceX(xc), LogicalToDeviceY(yc), LogicalToDeviceXRel(radius), LogicalToDeviceYRel(radius), (wxCoord)alpha1, (wxCoord) alpha2,
-                LogicalToDeviceX(xc), LogicalToDeviceY(yc) );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f %f %f %f %f ellipse\n"
+                       "%f %f lineto\n"
+                       "closepath\n"
+                       "stroke\n",
+                XLOG2DEV(xc), YLOG2DEV(yc),
+                XLOG2DEVREL(i_radius), YLOG2DEVREL(i_radius),
+                alpha1, alpha2,
+                XLOG2DEV(xc), YLOG2DEV(yc) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
-        CalcBoundingBox( xc-radius, yc-radius );
-        CalcBoundingBox( xc+radius, yc+radius );
+        CalcBoundingBox( xc-i_radius, yc-i_radius );
+        CalcBoundingBox( xc+i_radius, yc+i_radius );
     }
 }
 
@@ -478,11 +502,14 @@ void wxPostScriptDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,d
     {
         SetBrush( m_brush );
 
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d %d %d %d %d true ellipticarc\n"),
-                  LogicalToDeviceX(x+w/2), LogicalToDeviceY(y+h/2),
-                  LogicalToDeviceXRel(w/2), LogicalToDeviceYRel(h/2),
-                  (wxCoord)sa, (wxCoord)ea );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f %f %f %f %f true ellipticarc\n",
+                  XLOG2DEV(x+w/2), YLOG2DEV(y+h/2),
+                  XLOG2DEVREL(w/2), YLOG2DEVREL(h/2),
+                  sa, ea );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( x ,y );
         CalcBoundingBox( x+w, y+h );
@@ -492,11 +519,14 @@ void wxPostScriptDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,d
     {
         SetPen( m_pen );
 
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d %d %d %d %d false ellipticarc\n"),
-                LogicalToDeviceX(x+w/2), LogicalToDeviceY(y+h/2),
-                LogicalToDeviceXRel(w/2), LogicalToDeviceYRel(h/2),
-                (wxCoord)sa, (wxCoord)ea );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f %f %f %f %f false ellipticarc\n",
+                  XLOG2DEV(x+w/2), YLOG2DEV(y+h/2),
+                  XLOG2DEVREL(w/2), YLOG2DEVREL(h/2),
+                  sa, ea );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( x ,y );
         CalcBoundingBox( x+w, y+h );
@@ -511,12 +541,15 @@ void wxPostScriptDC::DoDrawPoint (wxCoord x, wxCoord y)
 
     SetPen (m_pen);
 
-    PsPrintf( wxT("newpath\n")
-              wxT("%d %d moveto\n")
-              wxT("%d %d lineto\n")
-              wxT("stroke\n"),
-            LogicalToDeviceX(x),   LogicalToDeviceY(y),
-            LogicalToDeviceX(x+1), LogicalToDeviceY(y) );
+    wxString buffer;
+    buffer.Printf( "newpath\n"
+                   "%f %f moveto\n"
+                   "%f %f lineto\n"
+                   "stroke\n",
+            XLOG2DEV(x),   YLOG2DEV(y),
+            XLOG2DEV(x+1), YLOG2DEV(y) );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 
     CalcBoundingBox( x, y );
 }
@@ -533,19 +566,24 @@ void wxPostScriptDC::DoDrawPolygon (int n, wxPoint points[], wxCoord xoffset, wx
 
         PsPrint( "newpath\n" );
 
-        wxCoord xx = LogicalToDeviceX(points[0].x + xoffset);
-        wxCoord yy = LogicalToDeviceY(points[0].y + yoffset);
+        double xx = XLOG2DEV(points[0].x + xoffset);
+        double yy = YLOG2DEV(points[0].y + yoffset);
 
-        PsPrintf( wxT("%d %d moveto\n"), xx, yy );
+        wxString buffer;
+        buffer.Printf( "%f %f moveto\n", xx, yy );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( points[0].x + xoffset, points[0].y + yoffset );
 
         for (int i = 1; i < n; i++)
         {
-            xx = LogicalToDeviceX(points[i].x + xoffset);
-            yy = LogicalToDeviceY(points[i].y + yoffset);
+            xx = XLOG2DEV(points[i].x + xoffset);
+            yy = YLOG2DEV(points[i].y + yoffset);
 
-            PsPrintf( wxT("%d %d lineto\n"), xx, yy );
+            buffer.Printf( "%f %f lineto\n", xx, yy );
+            buffer.Replace( ",", "." );
+            PsPrint( buffer );
 
             CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset);
         }
@@ -559,19 +597,24 @@ void wxPostScriptDC::DoDrawPolygon (int n, wxPoint points[], wxCoord xoffset, wx
 
         PsPrint( "newpath\n" );
 
-        wxCoord xx = LogicalToDeviceX(points[0].x + xoffset);
-        wxCoord yy = LogicalToDeviceY(points[0].y + yoffset);
+        double xx = XLOG2DEV(points[0].x + xoffset);
+        double yy = YLOG2DEV(points[0].y + yoffset);
 
-        PsPrintf( wxT("%d %d moveto\n"), xx, yy );
+        wxString buffer;
+        buffer.Printf( "%f %f moveto\n", xx, yy );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( points[0].x + xoffset, points[0].y + yoffset );
 
         for (int i = 1; i < n; i++)
         {
-            xx = LogicalToDeviceX(points[i].x + xoffset);
-            yy = LogicalToDeviceY(points[i].y + yoffset);
+            xx = XLOG2DEV(points[i].x + xoffset);
+            yy = YLOG2DEV(points[i].y + yoffset);
 
-            PsPrintf( wxT("%d %d lineto\n"), xx, yy );
+            buffer.Printf( "%f %f lineto\n", xx, yy );
+            buffer.Replace( ",", "." );
+            PsPrint( buffer );
 
             CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset);
         }
@@ -596,19 +639,24 @@ void wxPostScriptDC::DoDrawPolyPolygon (int n, int count[], wxPoint points[], wx
         int ofs = 0;
         for (int i = 0; i < n; ofs += count[i++])
         {
-            wxCoord xx = LogicalToDeviceX(points[ofs].x + xoffset);
-            wxCoord yy = LogicalToDeviceY(points[ofs].y + yoffset);
+            double xx = XLOG2DEV(points[ofs].x + xoffset);
+            double yy = YLOG2DEV(points[ofs].y + yoffset);
 
-            PsPrintf( wxT("%d %d moveto\n"), xx, yy );
+            wxString buffer;
+            buffer.Printf( "%f %f moveto\n", xx, yy );
+            buffer.Replace( ",", "." );
+            PsPrint( buffer );
 
             CalcBoundingBox( points[ofs].x + xoffset, points[ofs].y + yoffset );
 
             for (int j = 1; j < count[i]; j++)
             {
-                xx = LogicalToDeviceX(points[ofs+j].x + xoffset);
-                yy = LogicalToDeviceY(points[ofs+j].y + yoffset);
+                xx = XLOG2DEV(points[ofs+j].x + xoffset);
+                yy = YLOG2DEV(points[ofs+j].y + yoffset);
 
-                PsPrintf( wxT("%d %d lineto\n"), xx, yy );
+                buffer.Printf( "%f %f lineto\n", xx, yy );
+                buffer.Replace( ",", "." );
+                PsPrint( buffer );
 
                 CalcBoundingBox( points[ofs+j].x + xoffset, points[ofs+j].y + yoffset);
             }
@@ -625,19 +673,24 @@ void wxPostScriptDC::DoDrawPolyPolygon (int n, int count[], wxPoint points[], wx
         int ofs = 0;
         for (int i = 0; i < n; ofs += count[i++])
         {
-            wxCoord xx = LogicalToDeviceX(points[ofs].x + xoffset);
-            wxCoord yy = LogicalToDeviceY(points[ofs].y + yoffset);
+            double xx = XLOG2DEV(points[ofs].x + xoffset);
+            double yy = YLOG2DEV(points[ofs].y + yoffset);
 
-            PsPrintf( wxT("%d %d moveto\n"), xx, yy );
+            wxString buffer;
+            buffer.Printf( "%f %f moveto\n", xx, yy );
+            buffer.Replace( ",", "." );
+            PsPrint( buffer );
 
             CalcBoundingBox( points[ofs].x + xoffset, points[ofs].y + yoffset );
 
             for (int j = 1; j < count[i]; j++)
             {
-                xx = LogicalToDeviceX(points[ofs+j].x + xoffset);
-                yy = LogicalToDeviceY(points[ofs+j].y + yoffset);
+                xx = XLOG2DEV(points[ofs+j].x + xoffset);
+                yy = YLOG2DEV(points[ofs+j].y + yoffset);
 
-                PsPrintf( wxT("%d %d lineto\n"), xx, yy );
+                buffer.Printf( "%f %f lineto\n", xx, yy );
+                buffer.Replace( ",", "." );
+                PsPrint( buffer );
 
                 CalcBoundingBox( points[ofs+j].x + xoffset, points[ofs+j].y + yoffset);
             }
@@ -659,20 +712,23 @@ void wxPostScriptDC::DoDrawLines (int n, wxPoint points[], wxCoord xoffset, wxCo
 
     int i;
     for ( i =0; i<n ; i++ )
-    {
-        CalcBoundingBox( LogicalToDeviceX(points[i].x+xoffset), LogicalToDeviceY(points[i].y+yoffset));
-    }
-
-    PsPrintf( wxT("newpath\n")
-              wxT("%d %d moveto\n"),
-              LogicalToDeviceX(points[0].x+xoffset),
-              LogicalToDeviceY(points[0].y+yoffset) );
+        CalcBoundingBox( points[i].x+xoffset, points[i].y+yoffset );
+
+    wxString buffer;
+    buffer.Printf( "newpath\n"
+                   "%f %f moveto\n",
+              XLOG2DEV(points[0].x+xoffset),
+              YLOG2DEV(points[0].y+yoffset) );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 
     for (i = 1; i < n; i++)
     {
-        PsPrintf( wxT("%d %d lineto\n"),
-                  LogicalToDeviceX(points[i].x+xoffset),
-                  LogicalToDeviceY(points[i].y+yoffset) );
+        buffer.Printf( "%f %f lineto\n",
+                  XLOG2DEV(points[i].x+xoffset),
+                  YLOG2DEV(points[i].y+yoffset) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
     }
 
     PsPrint( "stroke\n" );
@@ -682,21 +738,27 @@ void wxPostScriptDC::DoDrawRectangle (wxCoord x, wxCoord y, wxCoord width, wxCoo
 {
     wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
 
+    width--;
+    height--;
+
     if (m_brush.GetStyle () != wxTRANSPARENT)
     {
         SetBrush( m_brush );
 
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d moveto\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d lineto\n")
-                  wxT("closepath\n")
-                  wxT("fill\n"),
-                LogicalToDeviceX(x),         LogicalToDeviceY(y),
-                LogicalToDeviceX(x + width), LogicalToDeviceY(y),
-                LogicalToDeviceX(x + width), LogicalToDeviceY(y + height),
-                LogicalToDeviceX(x),         LogicalToDeviceY(y + height) );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f moveto\n"
+                       "%f %f lineto\n"
+                       "%f %f lineto\n"
+                       "%f %f lineto\n"
+                       "closepath\n"
+                       "fill\n",
+                XLOG2DEV(x),         YLOG2DEV(y),
+                XLOG2DEV(x + width), YLOG2DEV(y),
+                XLOG2DEV(x + width), YLOG2DEV(y + height),
+                XLOG2DEV(x),         YLOG2DEV(y + height) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( x, y );
         CalcBoundingBox( x + width, y + height );
@@ -706,17 +768,20 @@ void wxPostScriptDC::DoDrawRectangle (wxCoord x, wxCoord y, wxCoord width, wxCoo
     {
         SetPen (m_pen);
 
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d moveto\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d lineto\n")
-                  wxT("closepath\n")
-                  wxT("stroke\n"),
-                LogicalToDeviceX(x),         LogicalToDeviceY(y),
-                LogicalToDeviceX(x + width), LogicalToDeviceY(y),
-                LogicalToDeviceX(x + width), LogicalToDeviceY(y + height),
-                LogicalToDeviceX(x),         LogicalToDeviceY(y + height) );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f moveto\n"
+                       "%f %f lineto\n"
+                       "%f %f lineto\n"
+                       "%f %f lineto\n"
+                       "closepath\n"
+                       "stroke\n",
+                XLOG2DEV(x),         YLOG2DEV(y),
+                XLOG2DEV(x + width), YLOG2DEV(y),
+                XLOG2DEV(x + width), YLOG2DEV(y + height),
+                XLOG2DEV(x),         YLOG2DEV(y + height) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( x, y );
         CalcBoundingBox( x + width, y + height );
@@ -727,6 +792,9 @@ void wxPostScriptDC::DoDrawRoundedRectangle (wxCoord x, wxCoord y, wxCoord width
 {
     wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
 
+    width--;
+    height--;
+
     if (radius < 0.0)
     {
         // Now, a negative radius is interpreted to mean
@@ -742,25 +810,28 @@ void wxPostScriptDC::DoDrawRoundedRectangle (wxCoord x, wxCoord y, wxCoord width
         SetBrush( m_brush );
 
         /* Draw rectangle anticlockwise */
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d %d 90 180 arc\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d %d 180 270 arc\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d %d 270 0 arc\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d %d 0 90 arc\n")
-                  wxT("%d %d lineto\n")
-                  wxT("closepath\n")
-                  wxT("fill\n"),
-                LogicalToDeviceX(x + rad), LogicalToDeviceY(y + rad), LogicalToDeviceXRel(rad),
-                LogicalToDeviceX(x), LogicalToDeviceY(y + height - rad),
-                LogicalToDeviceX(x + rad), LogicalToDeviceY(y + height - rad), LogicalToDeviceXRel(rad),
-                LogicalToDeviceX(x + width - rad), LogicalToDeviceY(y + height),
-                LogicalToDeviceX(x + width - rad), LogicalToDeviceY(y + height - rad), LogicalToDeviceXRel(rad),
-                LogicalToDeviceX(x + width), LogicalToDeviceY(y + rad),
-                LogicalToDeviceX(x + width - rad), LogicalToDeviceY(y + rad), LogicalToDeviceXRel(rad),
-                LogicalToDeviceX(x + rad), LogicalToDeviceY(y) );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f %f 90 180 arc\n"
+                       "%f %f lineto\n"
+                       "%f %f %f 180 270 arc\n"
+                       "%f %f lineto\n"
+                       "%f %f %f 270 0 arc\n"
+                       "%f %f lineto\n"
+                       "%f %f %f 0 90 arc\n"
+                       "%f %f lineto\n"
+                       "closepath\n"
+                       "fill\n",
+                XLOG2DEV(x + rad), YLOG2DEV(y + rad), XLOG2DEVREL(rad),
+                XLOG2DEV(x), YLOG2DEV(y + height - rad),
+                XLOG2DEV(x + rad), YLOG2DEV(y + height - rad), XLOG2DEVREL(rad),
+                XLOG2DEV(x + width - rad), YLOG2DEV(y + height),
+                XLOG2DEV(x + width - rad), YLOG2DEV(y + height - rad), XLOG2DEVREL(rad),
+                XLOG2DEV(x + width), YLOG2DEV(y + rad),
+                XLOG2DEV(x + width - rad), YLOG2DEV(y + rad), XLOG2DEVREL(rad),
+                XLOG2DEV(x + rad), YLOG2DEV(y) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( x, y );
         CalcBoundingBox( x + width, y + height );
@@ -771,25 +842,28 @@ void wxPostScriptDC::DoDrawRoundedRectangle (wxCoord x, wxCoord y, wxCoord width
         SetPen (m_pen);
 
         /* Draw rectangle anticlockwise */
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d %d 90 180 arc\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d %d 180 270 arc\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d %d 270 0 arc\n")
-                  wxT("%d %d lineto\n")
-                  wxT("%d %d %d 0 90 arc\n")
-                  wxT("%d %d lineto\n")
-                  wxT("closepath\n")
-                  wxT("stroke\n"),
-                LogicalToDeviceX(x + rad), LogicalToDeviceY(y + rad), LogicalToDeviceXRel(rad),
-                LogicalToDeviceX(x), LogicalToDeviceY(y + height - rad),
-                LogicalToDeviceX(x + rad), LogicalToDeviceY(y + height - rad), LogicalToDeviceXRel(rad),
-                LogicalToDeviceX(x + width - rad), LogicalToDeviceY(y + height),
-                LogicalToDeviceX(x + width - rad), LogicalToDeviceY(y + height - rad), LogicalToDeviceXRel(rad),
-                LogicalToDeviceX(x + width), LogicalToDeviceY(y + rad),
-                LogicalToDeviceX(x + width - rad), LogicalToDeviceY(y + rad), LogicalToDeviceXRel(rad),
-                LogicalToDeviceX(x + rad), LogicalToDeviceY(y) );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f %f 90 180 arc\n"
+                       "%f %f lineto\n"
+                       "%f %f %f 180 270 arc\n"
+                       "%f %f lineto\n"
+                       "%f %f %f 270 0 arc\n"
+                       "%f %f lineto\n"
+                       "%f %f %f 0 90 arc\n"
+                       "%f %f lineto\n"
+                       "closepath\n"
+                       "stroke\n",
+                XLOG2DEV(x + rad), YLOG2DEV(y + rad), XLOG2DEVREL(rad),
+                XLOG2DEV(x), YLOG2DEV(y + height - rad),
+                XLOG2DEV(x + rad), YLOG2DEV(y + height - rad), XLOG2DEVREL(rad),
+                XLOG2DEV(x + width - rad), YLOG2DEV(y + height),
+                XLOG2DEV(x + width - rad), YLOG2DEV(y + height - rad), XLOG2DEVREL(rad),
+                XLOG2DEV(x + width), YLOG2DEV(y + rad),
+                XLOG2DEV(x + width - rad), YLOG2DEV(y + rad), XLOG2DEVREL(rad),
+                XLOG2DEV(x + rad), YLOG2DEV(y) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( x, y );
         CalcBoundingBox( x + width, y + height );
@@ -800,15 +874,21 @@ void wxPostScriptDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord
 {
     wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
 
+    width--;
+    height--;
+
     if (m_brush.GetStyle () != wxTRANSPARENT)
     {
         SetBrush (m_brush);
 
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d %d %d 0 360 ellipse\n")
-                  wxT("fill\n"),
-                LogicalToDeviceX(x + width / 2), LogicalToDeviceY(y + height / 2),
-                LogicalToDeviceXRel(width / 2), LogicalToDeviceYRel(height / 2) );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f %f %f 0 360 ellipse\n"
+                       "fill\n",
+                XLOG2DEV(x + width / 2), YLOG2DEV(y + height / 2),
+                XLOG2DEVREL(width / 2), YLOG2DEVREL(height / 2) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( x - width, y - height );
         CalcBoundingBox( x + width, y + height );
@@ -818,11 +898,14 @@ void wxPostScriptDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord
     {
         SetPen (m_pen);
 
-        PsPrintf( wxT("newpath\n")
-                  wxT("%d %d %d %d 0 360 ellipse\n")
-                  wxT("stroke\n"),
-                LogicalToDeviceX(x + width / 2), LogicalToDeviceY(y + height / 2),
-                LogicalToDeviceXRel(width / 2), LogicalToDeviceYRel(height / 2) );
+        wxString buffer;
+        buffer.Printf( "newpath\n"
+                       "%f %f %f %f 0 360 ellipse\n"
+                       "stroke\n",
+                XLOG2DEV(x + width / 2), YLOG2DEV(y + height / 2),
+                XLOG2DEVREL(width / 2), YLOG2DEVREL(height / 2) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( x - width, y - height );
         CalcBoundingBox( x + width, y + height );
@@ -850,36 +933,39 @@ void wxPostScriptDC::DoDrawBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y,
     wxCoord w = image.GetWidth();
     wxCoord h = image.GetHeight();
 
-    wxCoord ww = LogicalToDeviceXRel(image.GetWidth());
-    wxCoord hh = LogicalToDeviceYRel(image.GetHeight());
-
-    wxCoord xx = LogicalToDeviceX(x);
-    wxCoord yy = LogicalToDeviceY(y + bitmap.GetHeight());
-
-    PsPrintf( wxT("/origstate save def\n")
-              wxT("20 dict begin\n")
-              wxT("/pix %d string def\n")
-              wxT("/grays %d string def\n")
-              wxT("/npixels 0 def\n")
-              wxT("/rgbindx 0 def\n")
-              wxT("%d %d translate\n")
-              wxT("%d %d scale\n")
-              wxT("%d %d 8\n")
-              wxT("[%d 0 0 %d 0 %d]\n")
-              wxT("{currentfile pix readhexstring pop}\n")
-              wxT("false 3 colorimage\n"),
+    double ww = XLOG2DEVREL(image.GetWidth());
+    double hh = YLOG2DEVREL(image.GetHeight());
+
+    double xx = XLOG2DEV(x);
+    double yy = YLOG2DEV(y + bitmap.GetHeight());
+
+    wxString buffer;
+    buffer.Printf( "/origstate save def\n"
+                   "20 dict begin\n"
+                   "/pix %d string def\n"
+                   "/grays %d string def\n"
+                   "/npixels 0 def\n"
+                   "/rgbindx 0 def\n"
+                   "%f %f translate\n"
+                   "%f %f scale\n"
+                   "%d %d 8\n"
+                   "[%d 0 0 %d 0 %d]\n"
+                   "{currentfile pix readhexstring pop}\n"
+                   "false 3 colorimage\n",
             w, w, xx, yy, ww, hh, w, h, w, -h, h );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 
     unsigned char* data = image.GetData();
 
     // size of the buffer = width*rgb(3)*hexa(2)+'\n'
-    wxCharBuffer buffer(w*6 + 1);
+    wxCharBuffer charbuffer(w*6 + 1);
     int firstDigit, secondDigit;
 
     //rows
     for (int j = 0; j < h; j++)
     {
-        char* bufferindex = buffer.data();
+        char* bufferindex = charbuffer.data();
 
         //cols
         for (int i = 0; i < w*3; i++)
@@ -893,7 +979,11 @@ void wxPostScriptDC::DoDrawBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y,
         }
         *(bufferindex++) = '\n';
         *bufferindex = 0;
-        PsPrint( buffer );
+
+        if (m_pstream)
+            fwrite( charbuffer, 1, strlen( charbuffer ), m_pstream );
+        else
+            PsPrint( charbuffer );
     }
 
     PsPrint( "end\n" );
@@ -986,13 +1076,11 @@ void wxPostScriptDC::SetFont( const wxFont& font )
     PsPrint( name );
     PsPrint( " findfont\n" );
 
-    char buffer[100];
-    sprintf( buffer, "%f scalefont setfont\n", LogicalToDeviceYRel(m_font.GetPointSize() * 1000) / 1000.0F);
-    // this is a hack - we must scale font size (in pts) according to m_scaleY but
-    // LogicalToDeviceYRel works with wxCoord type (int or longint). Se we first convert font size
-    // to 1/1000th of pt and then back.
-    for (int i = 0; i < 100; i++)
-        if (buffer[i] == ',') buffer[i] = '.';
+
+    double size = (double) m_font.GetPointSize();
+    wxString buffer;
+    buffer.Printf( "%f scalefont setfont\n", size * DEV2PS * m_scaleX );
+    buffer.Replace( ",", "." );
     PsPrint( buffer );
 }
 
@@ -1006,10 +1094,16 @@ void wxPostScriptDC::SetPen( const wxPen& pen )
 
     m_pen = pen;
 
-    char buffer[100];
-    sprintf( buffer, "%f setlinewidth\n", LogicalToDeviceXRel(1000 * m_pen.GetWidth()) / 1000.0f );
-    for (int i = 0; i < 100; i++)
-        if (buffer[i] == ',') buffer[i] = '.';
+    double width;
+
+    if (m_pen.GetWidth() <= 0)
+        width = 0.1;
+    else
+        width = (double) m_pen.GetWidth();
+
+    wxString buffer;
+    buffer.Printf( "%f setlinewidth\n", width * DEV2PS * m_scaleX );
+    buffer.Replace( ",", "." );
     PsPrint( buffer );
 
 /*
@@ -1044,12 +1138,12 @@ void wxPostScriptDC::SetPen( const wxPen& pen )
             PsPrint ("[");
             for (int i = 0; i < nDashes; ++i)
             {
-                sprintf( buffer, "%d ", dashes [i] );
+                buffer.Printf( "%d ", dashes [i] );
                 PsPrint( buffer );
             }
             PsPrint ("] 0 setdash\n");
-            psdash = 0; 
-        } 
+            psdash = 0;
+        }
         break;
         case wxSOLID:
         case wxTRANSPARENT:
@@ -1087,12 +1181,9 @@ void wxPostScriptDC::SetPen( const wxPen& pen )
         double bluePS = (double)(blue) / 255.0;
         double greenPS = (double)(green) / 255.0;
 
-        sprintf( buffer,
-            "%.8f %.8f %.8f setrgbcolor\n",
-            redPS, greenPS, bluePS );
-        for (int i = 0; i < 100; i++)
-            if (buffer[i] == ',') buffer[i] = '.';
-
+        wxString buffer;
+        buffer.Printf( "%f %f %f setrgbcolor\n", redPS, greenPS, bluePS );
+        buffer.Replace( ",", "." );
         PsPrint( buffer );
 
         m_currentRed = red;
@@ -1134,13 +1225,9 @@ void wxPostScriptDC::SetBrush( const wxBrush& brush )
         double bluePS = (double)(blue) / 255.0;
         double greenPS = (double)(green) / 255.0;
 
-        char buffer[100];
-        sprintf( buffer,
-                "%.8f %.8f %.8f setrgbcolor\n",
-                redPS, greenPS, bluePS );
-        for (int i = 0; i < 100; i++)
-            if (buffer[i] == ',') buffer[i] = '.';
-
+        wxString buffer;
+        buffer.Printf( "%f %f %f setrgbcolor\n", redPS, greenPS, bluePS );
+        buffer.Replace( ",", "." );
         PsPrint( buffer );
 
         m_currentRed = red;
@@ -1153,6 +1240,10 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
 {
     wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
 
+    const wxWX2MBbuf textbuf = text.mb_str();
+    if ( !textbuf )
+        return;
+
     if (m_textForegroundColour.Ok())
     {
         unsigned char red = m_textForegroundColour.Red();
@@ -1179,12 +1270,9 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
             double bluePS = (double)(blue) / 255.0;
             double greenPS = (double)(green) / 255.0;
 
-            char buffer[100];
-            sprintf( buffer,
-                "%.8f %.8f %.8f setrgbcolor\n",
-                redPS, greenPS, bluePS );
-            for (size_t i = 0; i < strlen(buffer); i++)
-                if (buffer[i] == ',') buffer[i] = '.';
+            wxString buffer;
+            buffer.Printf( "%f %f %f setrgbcolor\n", redPS, greenPS, bluePS );
+            buffer.Replace( ",", "." );
             PsPrint( buffer );
 
             m_currentRed = red;
@@ -1197,11 +1285,6 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
 
     GetTextExtent(text, &text_w, &text_h, &text_descent);
 
-    // VZ: this seems to be unnecessary, so taking it out for now, if it
-    //     doesn't create any problems, remove this comment entirely
-    //SetFont( m_font );
-
-
     int size = m_font.GetPointSize();
 
 //    wxCoord by = y + (wxCoord)floor( double(size) * 2.0 / 3.0 ); // approximate baseline
@@ -1209,10 +1292,12 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
 //        - note that there is still rounding error in text_descent!
     wxCoord by = y + size - text_descent; // baseline
 
-    PsPrintf( wxT("%d %d moveto\n"), LogicalToDeviceX(x), LogicalToDeviceY(by) );
+    wxString buffer;
+    buffer.Printf( "%f %f moveto\n", XLOG2DEV(x), YLOG2DEV(by) );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
     PsPrint( "(" );
 
-    const wxWX2MBbuf textbuf = text.mb_str();
     size_t len = strlen(textbuf);
     size_t i;
     for (i = 0; i < len; i++)
@@ -1222,16 +1307,17 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
         {
             /* Cope with special characters */
             PsPrint( "\\" );
-            PsPrint(c);
+            PsPrint( (char) c );
         }
         else if ( c >= 128 )
         {
             /* Cope with character codes > 127 */
-            PsPrintf( wxT("\\%o"), c);
+            buffer.Printf( "\\%o", c );
+            PsPrint( buffer );
         }
         else
         {
-            PsPrint(c);
+            PsPrint( (char) c );
         }
     }
 
@@ -1240,25 +1326,22 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
     if (m_font.GetUnderlined())
     {
         wxCoord uy = (wxCoord)(y + size - m_underlinePosition);
-        char buffer[100];
 
-        sprintf( buffer,
-                "gsave\n"
-                "%d %d moveto\n"
-                "%f setlinewidth\n"
-                "%d %d lineto\n"
-                "stroke\n"
-                "grestore\n",
-                LogicalToDeviceX(x), LogicalToDeviceY(uy),
+        buffer.Printf( "gsave\n"
+                       "%f %f moveto\n"
+                       "%f setlinewidth\n"
+                       "%f %f lineto\n"
+                       "stroke\n"
+                       "grestore\n",
+                XLOG2DEV(x), YLOG2DEV(uy),
                 m_underlineThickness,
-                LogicalToDeviceX(x + text_w), LogicalToDeviceY(uy) );
-        for (i = 0; i < 100; i++)
-            if (buffer[i] == ',') buffer[i] = '.';
+                XLOG2DEV(x + text_w), YLOG2DEV(uy) );
+        buffer.Replace( ",", "." );
         PsPrint( buffer );
     }
 
     CalcBoundingBox( x, y );
-    CalcBoundingBox( x + size * text.Length() * 2/3 , y );
+    CalcBoundingBox( x + size * text.length() * 2/3 , y );
 }
 
 void wxPostScriptDC::DoDrawRotatedText( const wxString& text, wxCoord x, wxCoord y, double angle )
@@ -1299,12 +1382,9 @@ void wxPostScriptDC::DoDrawRotatedText( const wxString& text, wxCoord x, wxCoord
             double bluePS = (double)(blue) / 255.0;
             double greenPS = (double)(green) / 255.0;
 
-            char buffer[100];
-            sprintf( buffer,
-                "%.8f %.8f %.8f setrgbcolor\n",
-                redPS, greenPS, bluePS );
-            for (int i = 0; i < 100; i++)
-                if (buffer[i] == ',') buffer[i] = '.';
+            wxString buffer;
+            buffer.Printf( "%f %f %f setrgbcolor\n", redPS, greenPS, bluePS );
+            buffer.Replace( ",", "." );
             PsPrint( buffer );
 
             m_currentRed = red;
@@ -1315,21 +1395,19 @@ void wxPostScriptDC::DoDrawRotatedText( const wxString& text, wxCoord x, wxCoord
 
     int size = m_font.GetPointSize();
 
-    PsPrintf( wxT("%d %d moveto\n"),
-            LogicalToDeviceX(x), LogicalToDeviceY(y));
+    wxString buffer;
+    buffer.Printf( "%f %f moveto\n", XLOG2DEV(x), YLOG2DEV(y));
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 
-    char buffer[100];
-    sprintf(buffer, "%.8f rotate\n", angle);
-    size_t i;
-    for (i = 0; i < 100; i++)
-    {
-        if (buffer[i] == ',') buffer[i] = '.';
-    }
-    PsPrint( buffer);
+    buffer.Printf( "%f rotate\n", angle );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 
     PsPrint( "(" );
     const wxWX2MBbuf textbuf = text.mb_str();
     size_t len = strlen(textbuf);
+    size_t i;
     for (i = 0; i < len; i++)
     {
         int c = (unsigned char) textbuf[i];
@@ -1337,26 +1415,24 @@ void wxPostScriptDC::DoDrawRotatedText( const wxString& text, wxCoord x, wxCoord
         {
             /* Cope with special characters */
             PsPrint( "\\" );
-            PsPrint(c);
+            PsPrint( (char) c );
         }
         else if ( c >= 128 )
         {
             /* Cope with character codes > 127 */
-            PsPrintf( wxT("\\%o"), c);
+            buffer.Printf( "\\%o", c);
+            PsPrint( buffer );
         }
         else
         {
-            PsPrint(c);
+            PsPrint( (char) c );
         }
     }
 
     PsPrint( ") show\n" );
 
-    sprintf( buffer, "%.8f rotate\n", -angle );
-    for (i = 0; i < 100; i++)
-    {
-        if (buffer[i] == ',') buffer[i] = '.';
-    }
+    buffer.Printf( "%f rotate\n", -angle );
+    buffer.Replace( ",", "." );
     PsPrint( buffer );
 
     if (m_font.GetUnderlined())
@@ -1365,25 +1441,22 @@ void wxPostScriptDC::DoDrawRotatedText( const wxString& text, wxCoord x, wxCoord
         wxCoord w, h;
         GetTextExtent(text, &w, &h);
 
-        sprintf( buffer,
+        buffer.Printf(
                 "gsave\n"
-                "%d %d moveto\n"
+                "%f %f moveto\n"
                 "%f setlinewidth\n"
-                "%d %d lineto\n"
+                "%f %f lineto\n"
                 "stroke\n"
                 "grestore\n",
-                LogicalToDeviceX(x), LogicalToDeviceY(uy),
+                XLOG2DEV(x), YLOG2DEV(uy),
                 m_underlineThickness,
-                LogicalToDeviceX(x + w), LogicalToDeviceY(uy) );
-        for (i = 0; i < 100; i++)
-        {
-            if (buffer[i] == ',') buffer[i] = '.';
-        }
+                XLOG2DEV(x + w), YLOG2DEV(uy) );
+        buffer.Replace( ",", "." );
         PsPrint( buffer );
     }
 
     CalcBoundingBox( x, y );
-    CalcBoundingBox( x + size * text.Length() * 2/3 , y );
+    CalcBoundingBox( x + size * text.length() * 2/3 , y );
 }
 
 void wxPostScriptDC::SetBackground (const wxBrush& brush)
@@ -1428,11 +1501,14 @@ void wxPostScriptDC::DoDrawSpline( wxList *points )
          #endif
          (double)(y1 + d) / 2;
 
-    PsPrintf( wxT("newpath\n")
-              wxT("%d %d moveto\n")
-              wxT("%d %d lineto\n"),
-            LogicalToDeviceX((wxCoord)x1), LogicalToDeviceY((wxCoord)y1),
-            LogicalToDeviceX((wxCoord)x3), LogicalToDeviceY((wxCoord)y3) );
+    wxString buffer;
+    buffer.Printf( "newpath\n"
+                   "%f %f moveto\n"
+                   "%f %f lineto\n",
+            XLOG2DEV(wxRound(x1)), YLOG2DEV(wxRound(y1)),
+            XLOG2DEV(wxRound(x3)), YLOG2DEV(wxRound(y3)) );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 
     CalcBoundingBox( (wxCoord)x1, (wxCoord)y1 );
     CalcBoundingBox( (wxCoord)x3, (wxCoord)y3 );
@@ -1451,10 +1527,12 @@ void wxPostScriptDC::DoDrawSpline( wxList *points )
         x3 = (double)(x2 + c) / 2;
         y3 = (double)(y2 + d) / 2;
 
-        PsPrintf( wxT("%d %d %d %d %d %d DrawSplineSection\n"),
-            LogicalToDeviceX((wxCoord)x1), LogicalToDeviceY((wxCoord)y1),
-            LogicalToDeviceX((wxCoord)x2), LogicalToDeviceY((wxCoord)y2),
-            LogicalToDeviceX((wxCoord)x3), LogicalToDeviceY((wxCoord)y3) );
+        buffer.Printf( "%f %f %f %f %f %f DrawSplineSection\n",
+            XLOG2DEV(wxRound(x1)), YLOG2DEV(wxRound(y1)),
+            XLOG2DEV(wxRound(x2)), YLOG2DEV(wxRound(y2)),
+            XLOG2DEV(wxRound(x3)), YLOG2DEV(wxRound(y3)) );
+        buffer.Replace( ",", "." );
+        PsPrint( buffer );
 
         CalcBoundingBox( (wxCoord)x1, (wxCoord)y1 );
         CalcBoundingBox( (wxCoord)x3, (wxCoord)y3 );
@@ -1467,9 +1545,9 @@ void wxPostScriptDC::DoDrawSpline( wxList *points )
        next-to-last and last point respectively, in the point list
      */
 
-    PsPrintf( wxT("%d %d lineto\n")
-              wxT("stroke\n"),
-            LogicalToDeviceX((wxCoord)c), LogicalToDeviceY((wxCoord)d) );
+    buffer.Printf( "%f %f lineto\nstroke\n", XLOG2DEV(wxRound(c)), YLOG2DEV(wxRound(d)) );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 }
 #endif // wxUSE_SPLINES
 
@@ -1479,26 +1557,77 @@ wxCoord wxPostScriptDC::GetCharWidth() const
     return (wxCoord) (GetCharHeight() * 72.0 / 120.0);
 }
 
+void wxPostScriptDC::SetPrintData(const wxPrintData& data)
+{
+    m_printData = data;
 
+    wxPaperSize id = m_printData.GetPaperId();
+    wxPrintPaperType *paper = wxThePrintPaperDatabase->FindPaperType(id);
+    if (!paper) paper = wxThePrintPaperDatabase->FindPaperType(wxPAPER_A4);
+    int w = 595;
+    int h = 842;
+    if (paper)
+    {
+        w = paper->GetSizeDeviceUnits().x;
+        h = paper->GetSizeDeviceUnits().y;
+    }
+
+    if (m_printData.GetOrientation() == wxLANDSCAPE)
+        m_pageHeight = w * PS2DEV;
+    else
+        m_pageHeight = h * PS2DEV;
+}
+
+#if wxUSE_NEW_DC
+#else
 void wxPostScriptDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
 {
-    wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
+    wxDCBase::SetAxisOrientation(xLeftRight,yBottomUp);
+}
 
-    m_signX = (xLeftRight ? 1 : -1);
-    m_signY = (yBottomUp  ? 1 : -1);
+void wxPostScriptDC::SetMapMode(int mode)
+{
+    wxDCBase::SetMapMode(mode);
+}
 
-    ComputeScaleAndOrigin();
+void wxPostScriptDC::SetUserScale(double x, double y)
+{
+    wxDCBase::SetUserScale(x,y);
 }
 
-void wxPostScriptDC::SetDeviceOrigin( wxCoord x, wxCoord y )
+void wxPostScriptDC::SetLogicalScale(double x, double y)
 {
-    wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
+    wxDCBase::SetLogicalScale(x,y);
+}
 
-    int h = 0;
-    int w = 0;
-    GetSize( &w, &h );
+void wxPostScriptDC::SetLogicalOrigin(wxCoord x, wxCoord y)
+{
+    wxDCBase::SetLogicalOrigin(x,y);
+}
 
-    wxDC::SetDeviceOrigin( x, h-y );
+void wxPostScriptDC::SetDeviceOrigin(wxCoord x, wxCoord y)
+{
+    wxDCBase::SetDeviceOrigin(x,y);
+}
+#endif
+
+void wxPostScriptDC::ComputeScaleAndOrigin()
+{
+    const wxRealPoint origScale(m_scaleX, m_scaleY);
+
+#if wxUSE_NEW_DC
+    wxImplDC::ComputeScaleAndOrigin();
+#else
+    wxDC::ComputeScaleAndOrigin();
+#endif
+
+    // If scale has changed call SetPen to recalulate the line width
+    // and SetFont to recalculate font size
+    if ( wxRealPoint(m_scaleX, m_scaleY) != origScale && m_pen.IsOk() )
+    {
+        SetPen( m_pen );
+        SetFont( m_font  );
+    }
 }
 
 void wxPostScriptDC::DoGetSize(int* width, int* height) const
@@ -1524,8 +1653,11 @@ void wxPostScriptDC::DoGetSize(int* width, int* height) const
         h = tmp;
     }
 
-    if (width) *width = (int)(w * ms_PSScaleFactor);
-    if (height) *height = (int)(h * ms_PSScaleFactor);
+    if (width)
+        *width = wxRound( w * PS2DEV );
+
+    if (height)
+        *height = wxRound( h * PS2DEV );
 }
 
 void wxPostScriptDC::DoGetSizeMM(int *width, int *height) const
@@ -1558,8 +1690,7 @@ void wxPostScriptDC::DoGetSizeMM(int *width, int *height) const
 // Resolution in pixels per logical inch
 wxSize wxPostScriptDC::GetPPI(void) const
 {
-    return wxSize((int)(72 * ms_PSScaleFactor),
-                  (int)(72 * ms_PSScaleFactor));
+    return wxSize( DPI, DPI );
 }
 
 
@@ -1588,37 +1719,45 @@ bool wxPostScriptDC::StartDoc( const wxString& message )
     m_ok = true;
     m_title = message;
 
+    wxString buffer;
+
     PsPrint( "%!PS-Adobe-2.0\n" );
-    PsPrintf( wxT("%%%%Title: %s\n"), m_title.c_str() );
+
+    buffer.Printf( "%%%%Title: %s\n", m_title );
+    PsPrint( buffer );
     PsPrint( "%%Creator: wxWidgets PostScript renderer\n" );
-    PsPrintf( wxT("%%%%CreationDate: %s\n"), wxNow().c_str() );
+
+    buffer.Printf( "%%%%CreationDate: %s\n", wxNow() );
+    PsPrint( buffer );
+
     if (m_printData.GetOrientation() == wxLANDSCAPE)
         PsPrint( "%%Orientation: Landscape\n" );
     else
         PsPrint( "%%Orientation: Portrait\n" );
 
-    // PsPrintf( wxT("%%%%Pages: %d\n"), (wxPageNumber - 1) );
-
     const wxChar *paper;
     switch (m_printData.GetPaperId())
     {
-       case wxPAPER_LETTER: paper = wxT("Letter"); break;             // Letter: paper ""; 8 1/2 by 11 inches
-       case wxPAPER_LEGAL: paper = wxT("Legal"); break;              // Legal, 8 1/2 by 14 inches
-       case wxPAPER_A4: paper = wxT("A4"); break;          // A4 Sheet, 210 by 297 millimeters
+       case wxPAPER_LETTER: paper = wxT("Letter"); break;       // Letter: paper ""; 8 1/2 by 11 inches
+       case wxPAPER_LEGAL: paper = wxT("Legal"); break;         // Legal, 8 1/2 by 14 inches
+       case wxPAPER_A4: paper = wxT("A4"); break;               // A4 Sheet, 210 by 297 millimeters
        case wxPAPER_TABLOID: paper = wxT("Tabloid"); break;     // Tabloid, 11 by 17 inches
-       case wxPAPER_LEDGER: paper = wxT("Ledger"); break;      // Ledger, 17 by 11 inches
-       case wxPAPER_STATEMENT: paper = wxT("Statement"); break;   // Statement, 5 1/2 by 8 1/2 inches
-       case wxPAPER_EXECUTIVE: paper = wxT("Executive"); break;   // Executive, 7 1/4 by 10 1/2 inches
-       case wxPAPER_A3: paper = wxT("A3"); break;          // A3 sheet, 297 by 420 millimeters
-       case wxPAPER_A5: paper = wxT("A5"); break;          // A5 sheet, 148 by 210 millimeters
-       case wxPAPER_B4: paper = wxT("B4"); break;          // B4 sheet, 250 by 354 millimeters
-       case wxPAPER_B5: paper = wxT("B5"); break;          // B5 sheet, 182-by-257-millimeter paper
-       case wxPAPER_FOLIO: paper = wxT("Folio"); break;       // Folio, 8-1/2-by-13-inch paper
-       case wxPAPER_QUARTO: paper = wxT("Quaro"); break;      // Quarto, 215-by-275-millimeter paper
-       case wxPAPER_10X14: paper = wxT("10x14"); break;       // 10-by-14-inch sheet
+       case wxPAPER_LEDGER: paper = wxT("Ledger"); break;       // Ledger, 17 by 11 inches
+       case wxPAPER_STATEMENT: paper = wxT("Statement"); break; // Statement, 5 1/2 by 8 1/2 inches
+       case wxPAPER_EXECUTIVE: paper = wxT("Executive"); break; // Executive, 7 1/4 by 10 1/2 inches
+       case wxPAPER_A3: paper = wxT("A3"); break;               // A3 sheet, 297 by 420 millimeters
+       case wxPAPER_A5: paper = wxT("A5"); break;               // A5 sheet, 148 by 210 millimeters
+       case wxPAPER_B4: paper = wxT("B4"); break;               // B4 sheet, 250 by 354 millimeters
+       case wxPAPER_B5: paper = wxT("B5"); break;               // B5 sheet, 182-by-257-millimeter paper
+       case wxPAPER_FOLIO: paper = wxT("Folio"); break;         // Folio, 8-1/2-by-13-inch paper
+       case wxPAPER_QUARTO: paper = wxT("Quaro"); break;        // Quarto, 215-by-275-millimeter paper
+       case wxPAPER_10X14: paper = wxT("10x14"); break;         // 10-by-14-inch sheet
        default: paper = wxT("A4");
     }
-    PsPrintf( wxT("%%%%DocumentPaperSizes: %s\n"), paper );
+
+    buffer.Printf( "%%%%DocumentPaperSizes: %s\n", paper );
+    PsPrint( buffer );
+
     PsPrint( "%%EndComments\n\n" );
 
     PsPrint( "%%BeginProlog\n" );
@@ -1640,7 +1779,6 @@ bool wxPostScriptDC::StartDoc( const wxString& message )
     // set origin according to paper size
     SetDeviceOrigin( 0,0 );
 
-    wxPageNumber = 1;
     m_pageNumber = 1;
     return true;
 }
@@ -1673,10 +1811,10 @@ void wxPostScriptDC::EndDoc ()
 
     // Compute the bounding box.  Note that it is in the default user
     // coordinate system, thus we have to convert the values.
-    wxCoord minX = (wxCoord) LogicalToDeviceX(m_minX);
-    wxCoord minY = (wxCoord) LogicalToDeviceY(m_minY);
-    wxCoord maxX = (wxCoord) LogicalToDeviceX(m_maxX);
-    wxCoord maxY = (wxCoord) LogicalToDeviceY(m_maxY);
+    wxCoord minX = (wxCoord) XLOG2DEV(m_minX);
+    wxCoord minY = (wxCoord) YLOG2DEV(m_minY);
+    wxCoord maxX = (wxCoord) XLOG2DEV(m_maxX);
+    wxCoord maxY = (wxCoord) YLOG2DEV(m_maxY);
 
     // LOG2DEV may have changed the minimum to maximum vice versa
     if ( minX > maxX ) { wxCoord tmp = minX; minX = maxX; maxX = tmp; }
@@ -1749,48 +1887,38 @@ void wxPostScriptDC::StartPage()
 {
     wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
 
-    PsPrintf( wxT("%%%%Page: %d\n"), wxPageNumber++ );
+    wxString buffer;
+    buffer.Printf( wxT("%%%%Page: %d\n"), m_pageNumber++ );
+    PsPrint( buffer );
 
-    //  What is this one supposed to do? RR.
-//  *m_pstream << "matrix currentmatrix\n";
+#if 0
+    wxPostScriptPrintNativeData *data =
+        (wxPostScriptPrintNativeData *) m_printData.GetNativeData();
 
-    // Added by Chris Breeze
+    wxCoord translate_x = (wxCoord)data->GetPrinterTranslateX();
+    wxCoord translate_y = (wxCoord)data->GetPrinterTranslateY();
 
-    // Each page starts with an "initgraphics" which resets the
-    // transformation and so we need to reset the origin
-    // (and rotate the page for landscape printing)
+    buffer.Printf( "%d %d translate\n", translate_x, translate_y );
+    PsPrint( buffer );
 
-    // Output scaling
-    wxCoord translate_x, translate_y;
-    double scale_x, scale_y;
+    double scale_x = data->GetPrinterScaleX();
+    double scale_y = data->GetPrinterScaleY();
 
-    wxPostScriptPrintNativeData *data =
-        (wxPostScriptPrintNativeData *) m_printData.GetNativeData();
+    buffer.Printf( "%f %f scale\n", scale_x, scale_y );
+    buffer.Replace( ",", "." );
+    PsPrint( buffer );
 
-    translate_x = (wxCoord)data->GetPrinterTranslateX();
-    translate_y = (wxCoord)data->GetPrinterTranslateY();
+#endif
 
-    scale_x = data->GetPrinterScaleX();
-    scale_y = data->GetPrinterScaleY();
+    // Each page starts with an "initgraphics" which resets the
+    // transformation and so we need to rotate the page for
+    // landscape printing)
+
+    // I copied this one from a PostScript tutorial, but to no avail. RR.
+    // PsPrint( "90 rotate llx neg ury nef translate\n" );
 
     if (m_printData.GetOrientation() == wxLANDSCAPE)
-    {
-        int h;
-        GetSize( (int*) NULL, &h );
-        translate_y -= h;
         PsPrint( "90 rotate\n" );
-        // I copied this one from a PostScript tutorial, but to no avail. RR.
-        // PsPrint( "90 rotate llx neg ury nef translate\n" );
-    }
-
-    char buffer[100];
-    sprintf( buffer, "%.8f %.8f scale\n", scale_x / ms_PSScaleFactor,
-            scale_y / ms_PSScaleFactor);
-    for (int i = 0; i < 100; i++)
-        if (buffer[i] == ',') buffer[i] = '.';
-    PsPrint( buffer );
-
-    PsPrintf( wxT("%d %d translate\n"), translate_x, translate_y );
 }
 
 void wxPostScriptDC::EndPage ()
@@ -1831,14 +1959,41 @@ wxCoord wxPostScriptDC::GetCharHeight() const
         return 12;
 }
 
+void wxPostScriptDC::PsPrint( const wxString& str )
+{
+    const wxCharBuffer psdata(str.utf8_str());
+
+    wxPostScriptPrintNativeData *data =
+        (wxPostScriptPrintNativeData *) m_printData.GetNativeData();
+
+    switch (m_printData.GetPrintMode())
+    {
+#if wxUSE_STREAMS
+        // append to output stream
+        case wxPRINT_MODE_STREAM:
+            {
+                wxOutputStream* outputstream = data->GetOutputStream();
+                wxCHECK_RET( outputstream, wxT("invalid outputstream") );
+                outputstream->Write( psdata, strlen( psdata ) );
+            }
+            break;
+#endif // wxUSE_STREAMS
+
+        // save data into file
+        default:
+            wxCHECK_RET( m_pstream, wxT("invalid postscript dc") );
+            fwrite( psdata, 1, strlen( psdata ), m_pstream );
+    }
+}
+
 void wxPostScriptDC::DoGetTextExtent(const wxString& string,
                                      wxCoord *x, wxCoord *y,
                                      wxCoord *descent, wxCoord *externalLeading,
-                                     wxFont *theFont ) const
+                                     const wxFont *theFont ) const
 {
-    wxFont *fontToUse = theFont;
+    const wxFont *fontToUse = theFont;
 
-    if (!fontToUse) fontToUse = (wxFont*) &m_font;
+    if (!fontToUse) fontToUse = &m_font;
 
     wxCHECK_RET( fontToUse, wxT("GetTextExtent: no font defined") );
 
@@ -1855,6 +2010,10 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
 
     const wxWX2MBbuf strbuf = string.mb_str();
 
+    // conversion failed (non e.g. ISO characters)
+    if ( !strbuf )
+        return;
+
 #if !wxUSE_AFM_FOR_POSTSCRIPT
     /* Provide a VERY rough estimate (avoid using it).
      * Produces accurate results for mono-spaced font
@@ -1890,7 +2049,7 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
     /        in 'points' (1/72 of an inch). this should later on be
     /        changed to depend on the mapping mode.
     /  CAVE: the path to the AFM files must be set before calling this
-    /        function. this is usually done by a call like the following:
+    /        fun3B3Bction. this is usually done by a call like the following:
     /        wxSetAFMPath("d:\\wxw161\\afm\\");
     /
     /  example:
@@ -2135,9 +2294,9 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
         // VS: dirty, but is there any better solution?
         double *pt;
         pt = (double*) &m_underlinePosition;
-        *pt = LogicalToDeviceYRel((wxCoord)(UnderlinePosition * fontToUse->GetPointSize())) / 1000.0f;
+        *pt = YLOG2DEVREL((wxCoord)(UnderlinePosition * fontToUse->GetPointSize())) / 1000.0f;
         pt = (double*) &m_underlineThickness;
-        *pt = LogicalToDeviceYRel((wxCoord)(UnderlineThickness * fontToUse->GetPointSize())) / 1000.0f;
+        *pt = YLOG2DEVREL((wxCoord)(UnderlineThickness * fontToUse->GetPointSize())) / 1000.0f;
 
     }
 
@@ -2199,70 +2358,7 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
     // Use AFM
 }
 
-// print postscript datas via required method (file, stream)
-void wxPostScriptDC::PsPrintf( const wxChar* fmt, ... )
-{
-    va_list argptr;
-    va_start(argptr, fmt);
-
-    PsPrint( wxString::FormatV( fmt, argptr ).c_str() );
-}
-
-void wxPostScriptDC::PsPrint( const char* psdata )
-{
-    wxPostScriptPrintNativeData *data =
-        (wxPostScriptPrintNativeData *) m_printData.GetNativeData();
-
-    switch (m_printData.GetPrintMode())
-    {
-#if wxUSE_STREAMS
-        // append to output stream
-        case wxPRINT_MODE_STREAM:
-            {
-                wxOutputStream* outputstream = data->GetOutputStream();
-                wxCHECK_RET( outputstream, wxT("invalid outputstream") );
-                outputstream->Write( psdata, strlen( psdata ) );
-            }
-            break;
-#endif // wxUSE_STREAMS
-
-        // save data into file
-        default:
-            wxCHECK_RET( m_pstream, wxT("invalid postscript dc") );
-            fwrite( psdata, 1, strlen( psdata ), m_pstream );
-    }
-}
-
-void wxPostScriptDC::PsPrint( int ch )
-{
-    wxPostScriptPrintNativeData *data =
-        (wxPostScriptPrintNativeData *) m_printData.GetNativeData();
-
-    switch (m_printData.GetPrintMode())
-    {
-#if wxUSE_STREAMS
-        // append to output stream
-        case wxPRINT_MODE_STREAM:
-            {
-                wxOutputStream* outputstream = data->GetOutputStream();
-                wxCHECK_RET( outputstream, wxT("invalid outputstream") );
-                outputstream->PutC( (char)ch );
-            }
-            break;
-#endif // wxUSE_STREAMS
-
-        // save data into file
-        default:
-            wxCHECK_RET( m_pstream, wxT("invalid postscript dc") );
-            fputc( ch, m_pstream );
-    }
-}
-
-#endif
-  // wxUSE_POSTSCRIPT
-
-#endif
-  // wxUSE_PRINTING_ARCHITECTURE
 
+#endif // wxUSE_PRINTING_ARCHITECTURE && wxUSE_POSTSCRIPT
 
 // vi:sts=4:sw=4:et