1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Generic wxPostScriptDC implementation 
   4 // Author:      Julian Smart, Robert Roebling, Markus Holzhem 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation 
  17 #include "wx/wxprec.h" 
  30 #include "wx/dcmemory.h" 
  33 #include "wx/filedlg.h" 
  35 #include "wx/msgdlg.h" 
  38 #include "wx/generic/dcpsg.h" 
  39 #include "wx/generic/prntdlgg.h" 
  40 #include "wx/button.h" 
  41 #include "wx/stattext.h" 
  42 #include "wx/radiobox.h" 
  43 #include "wx/textctrl.h" 
  44 #include "wx/prntbase.h" 
  69 //----------------------------------------------------------------------------- 
  70 // start and end of document/page 
  71 //----------------------------------------------------------------------------- 
  73 static const char *wxPostScriptHeaderEllipse 
= "\ 
  74 /ellipsedict 8 dict def\n\ 
  75 ellipsedict /mtrx matrix put\n\ 
  79     /startangle exch def\n\ 
  84     /savematrix mtrx currentmatrix def\n\ 
  87     0 0 1 startangle endangle arc\n\ 
  88     savematrix setmatrix\n\ 
  93 static const char *wxPostScriptHeaderEllipticArc
= "\ 
  94 /ellipticarcdict 8 dict def\n\ 
  95 ellipticarcdict /mtrx matrix put\n\ 
  97 { ellipticarcdict begin\n\ 
 100   /startangle exch def\n\ 
 105   /savematrix mtrx currentmatrix def\n\ 
 108   do_fill { 0 0 moveto } if\n\ 
 109   0 0 1 startangle endangle arc\n\ 
 110   savematrix setmatrix\n\ 
 111   do_fill { fill }{ stroke } ifelse\n\ 
 115 static const char *wxPostScriptHeaderSpline 
= "\ 
 116 /DrawSplineSection {\n\ 
 123     /xa x1 x2 x1 sub 0.666667 mul add def\n\ 
 124     /ya y1 y2 y1 sub 0.666667 mul add def\n\ 
 125     /xb x3 x2 x3 sub 0.666667 mul add def\n\ 
 126     /yb y3 y2 y3 sub 0.666667 mul add def\n\ 
 128     xa ya xb yb x3 y3 curveto\n\ 
 132 static const char *wxPostScriptHeaderColourImage 
= "\ 
 133 % define 'colorimage' if it isn't defined\n\ 
 134 %   ('colortogray' and 'mergeprocs' come from xwd2ps\n\ 
 136 /colorimage where   % do we know about 'colorimage'?\n\ 
 137   { pop }           % yes: pop off the 'dict' returned\n\ 
 138   {                 % no:  define one\n\ 
 139     /colortogray {  % define an RGB->I function\n\ 
 140       /rgbdata exch store    % call input 'rgbdata'\n\ 
 141       rgbdata length 3 idiv\n\ 
 142       /npixls exch store\n\ 
 144       0 1 npixls 1 sub {\n\ 
 146         rgbdata rgbindx       get 20 mul    % Red\n\ 
 147         rgbdata rgbindx 1 add get 32 mul    % Green\n\ 
 148         rgbdata rgbindx 2 add get 12 mul    % Blue\n\ 
 149         add add 64 idiv      % I = .5G + .31R + .18B\n\ 
 151         /rgbindx rgbindx 3 add store\n\ 
 153       grays 0 npixls getinterval\n\ 
 156     % Utility procedure for colorimage operator.\n\ 
 157     % This procedure takes two procedures off the\n\ 
 158     % stack and merges them into a single procedure.\n\ 
 160     /mergeprocs { % def\n\ 
 179     /colorimage { % def\n\ 
 180       pop pop     % remove 'false 3' operands\n\ 
 181       {colortogray} mergeprocs\n\ 
 184   } ifelse          % end of 'false' case\n\ 
 187 static char wxPostScriptHeaderReencodeISO1
[] = 
 189 "dup dup findfont dup length dict begin\n" 
 190 "{ 1 index /FID ne { def }{ pop pop } ifelse } forall\n" 
 191 "/Encoding ISOLatin1Encoding def\n" 
 192 "currentdict end definefont\n" 
 194 "/ISOLatin1Encoding [\n" 
 195 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 196 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 197 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 198 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 199 "/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright\n" 
 200 "/parenleft/parenright/asterisk/plus/comma/minus/period/slash\n" 
 201 "/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon\n" 
 202 "/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N\n" 
 203 "/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright\n" 
 204 "/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m\n" 
 205 "/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde\n" 
 206 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 207 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 208 "/.notdef/dotlessi/grave/acute/circumflex/tilde/macron/breve\n" 
 209 "/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut\n"; 
 211 static char wxPostScriptHeaderReencodeISO2
[] = 
 212 "/ogonek/caron/space/exclamdown/cent/sterling/currency/yen/brokenbar\n" 
 213 "/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot\n" 
 214 "/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior\n" 
 215 "/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine\n" 
 216 "/guillemotright/onequarter/onehalf/threequarters/questiondown\n" 
 217 "/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla\n" 
 218 "/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex\n" 
 219 "/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis\n" 
 220 "/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute\n" 
 221 "/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis\n" 
 222 "/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave\n" 
 223 "/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex\n" 
 224 "/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis\n" 
 225 "/yacute/thorn/ydieresis\n" 
 228 //------------------------------------------------------------------------------- 
 230 //------------------------------------------------------------------------------- 
 232 wxPostScriptDC::wxPostScriptDC () 
 234     m_pstream 
= (ofstream
*) NULL
; 
 244     m_underlinePosition 
= 0.0; 
 245     m_underlineThickness 
= 0.0; 
 247     m_signX 
=  1;  // default x-axis left to right 
 248     m_signY 
= -1;  // default y-axis bottom up -> top down 
 250     // Compatibility only 
 251     m_printData 
= * wxThePrintSetupData
; 
 254 wxPostScriptDC::wxPostScriptDC (const wxString
& file
, bool interactive
, wxWindow 
*parent
) 
 256     m_pstream 
= (ofstream
*) NULL
; 
 266     m_underlinePosition 
= 0.0; 
 267     m_underlineThickness 
= 0.0; 
 269     m_signX 
=  1;  // default x-axis left to right 
 270     m_signY 
= -1;  // default y-axis bottom up -> top down 
 272     Create(file
, interactive
, parent
); 
 275 bool wxPostScriptDC::Create(const wxString
& file
, bool interactive
, wxWindow 
*parent
) 
 277     m_isInteractive 
= interactive
; 
 280     m_printData
.SetFilename(file
); 
 283     // Can only send to file in Windows 
 284     m_printData
.SetPrintMode(wxPRINT_MODE_FILE
); 
 289         if ((m_ok 
= PrinterDialog (parent
) ) == FALSE
) return FALSE
; 
 299 wxPostScriptDC::wxPostScriptDC (const wxPrintData
& printData
) 
 301     m_pstream 
= (ofstream
*) NULL
; 
 311     m_underlinePosition 
= 0.0; 
 312     m_underlineThickness 
= 0.0; 
 314     m_signX 
=  1;  // default x-axis left to right 
 315     m_signY 
= -1;  // default y-axis bottom up -> top down 
 317     m_printData 
= printData
; 
 320 wxPostScriptDC::~wxPostScriptDC () 
 322     if (m_pstream
) delete m_pstream
; 
 325 bool wxPostScriptDC::Ok() const 
 330 // This dialog is deprecated now: use wxGenericPrintDialog or the printing framework 
 331 bool wxPostScriptDC::PrinterDialog(wxWindow 
*parent
) 
 333     wxPostScriptPrintDialog 
dialog( parent
, _("Printer Settings"), wxPoint(150, 150), wxSize(400, 400), 
 334                                     wxDEFAULT_DIALOG_STYLE 
| wxDIALOG_MODAL 
); 
 335     m_ok 
= (dialog
.ShowModal () == wxID_OK
); 
 337     if (!m_ok
) return FALSE
; 
 339     if ((m_printData
.GetFilename() == "") && 
 340         (m_printData
.GetPrintMode() == wxPRINT_MODE_PREVIEW  
|| 
 341          m_printData
.GetPrintMode() == wxPRINT_MODE_PRINTER
)) 
 345       m_printData
.SetFilename("preview"); 
 347       // For PS_PRINTER action this depends on a Unix-style print spooler 
 348       // since the wx_printer_file can be destroyed during a session 
 349       // @@@ TODO: a Windows-style answer for non-Unix 
 351       wxGetUserId (userId
, sizeof (userId
) / sizeof (char)); 
 353       strcpy (tmp
, "/tmp/preview_"); 
 354       strcat (tmp
, userId
); 
 355       m_printData
.SetFilename(tmp
); 
 358       strcpy(tmp2
, m_printData
.GetFilename()); 
 359       strcat (tmp2
, ".ps"); 
 360       m_printData
.SetFilename(tmp2
); 
 362     else if ((m_printData
.GetFilename() == "") && (m_printData
.GetPrintMode() == wxPRINT_MODE_FILE
)) 
 364       wxString file 
= wxSaveFileSelector (_("PostScript"), "ps"); 
 365       if ( file
.IsEmpty() ) 
 371       m_printData
.SetFilename(file
); 
 378 void wxPostScriptDC::SetClippingRegion (long x
, long y
, long w
, long h
) 
 380     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 382     if (m_clipping
) return; 
 384     wxDC::SetClippingRegion( x
, y
, w
, h 
); 
 387     *m_pstream 
<< "gsave\n" 
 389            << XLOG2DEV(x
)   << " " << YLOG2DEV(y
)   << " moveto\n" 
 390            << XLOG2DEV(x
+w
) << " " << YLOG2DEV(y
)   << " lineto\n" 
 391            << XLOG2DEV(x
+w
) << " " << YLOG2DEV(y
+h
) << " lineto\n" 
 392            << XLOG2DEV(x
)   << " " << YLOG2DEV(y
+h
) << " lineto\n" 
 393                << "closepath clip newpath\n"; 
 396 void wxPostScriptDC::SetClippingRegion( const wxRegion 
&WXUNUSED(region
) ) 
 400 void wxPostScriptDC::DestroyClippingRegion() 
 402     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 404     wxDC::DestroyClippingRegion(); 
 409         *m_pstream 
<< "grestore\n"; 
 413 void wxPostScriptDC::Clear() 
 415     wxFAIL_MSG( "wxPostScriptDC::Clear not implemented." ); 
 418 void wxPostScriptDC::FloodFill (long WXUNUSED(x
), long WXUNUSED(y
), const wxColour 
&WXUNUSED(col
), int WXUNUSED(style
)) 
 420     wxFAIL_MSG( "wxPostScriptDC::FloodFill not implemented." ); 
 423 bool wxPostScriptDC::GetPixel (long WXUNUSED(x
), long WXUNUSED(y
), wxColour 
* WXUNUSED(col
)) const 
 425     wxFAIL_MSG( "wxPostScriptDC::GetPixel not implemented." ); 
 429 void wxPostScriptDC::CrossHair (long WXUNUSED(x
), long WXUNUSED(y
)) 
 431     wxFAIL_MSG( "wxPostScriptDC::CrossHair not implemented." ); 
 434 void wxPostScriptDC::DrawLine (long x1
, long y1
, long x2
, long y2
) 
 436     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 438     if  (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 442     *m_pstream 
<< "newpath\n" 
 443            <<  XLOG2DEV(x1
) << " " <<  YLOG2DEV (y1
) << " moveto\n" 
 444            <<  XLOG2DEV(x2
) << " " <<  YLOG2DEV (y2
) << " lineto\n" 
 447     CalcBoundingBox( x1
, y1 
); 
 448     CalcBoundingBox( x2
, y2 
); 
 451 #define RAD2DEG 57.29577951308 
 453 void wxPostScriptDC::DrawArc (long x1
, long y1
, long x2
, long y2
, long xc
, long yc
) 
 455     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 459     long radius 
= (long) sqrt(dx
*dx
+dy
*dy
); 
 460     double alpha1
, alpha2
; 
 462     if (x1 
== x2 
&& y1 
== y2
) 
 466     } else if (radius 
== 0.0) 
 468     alpha1 
= alpha2 
= 0.0; 
 471     alpha1 
= (x1 
- xc 
== 0) ? 
 472         (y1 
- yc 
< 0) ? 90.0 : -90.0 : 
 473         -atan2(double(y1
-yc
), double(x1
-xc
)) * RAD2DEG
; 
 474     alpha2 
= (x2 
- xc 
== 0) ? 
 475         (y2 
- yc 
< 0) ? 90.0 : -90.0 : 
 476         -atan2(double(y2
-yc
), double(x2
-xc
)) * RAD2DEG
; 
 478     while (alpha1 
<= 0)   alpha1 
+= 360; 
 479     while (alpha2 
<= 0)   alpha2 
+= 360; // adjust angles to be between 
 480     while (alpha1 
> 360)  alpha1 
-= 360; // 0 and 360 degree 
 481     while (alpha2 
> 360)  alpha2 
-= 360; 
 483     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 486     *m_pstream 
<< "newpath\n" 
 487              << XLOG2DEV(xc
)        << " " 
 488          << YLOG2DEV(yc
)        << " " 
 489              << XLOG2DEVREL(radius
) << " " 
 490          << YLOG2DEVREL(radius
) << " " 
 492          << alpha2               
<< " ellipse\n" 
 493              << XLOG2DEV(xc
)        << " " 
 494          << YLOG2DEV(yc
)        << " lineto\n" 
 499     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 502     *m_pstream 
<< "newpath\n" 
 503              << XLOG2DEV(xc
)        << " " 
 504          << YLOG2DEV(yc
)        << " " 
 505              << XLOG2DEVREL(radius
) << " " 
 506          << YLOG2DEVREL(radius
) << " " 
 508          << alpha2               
<< " ellipse\n" 
 512     CalcBoundingBox( xc
-radius
, yc
-radius 
); 
 513     CalcBoundingBox( xc
+radius
, yc
+radius 
); 
 516 void wxPostScriptDC::DrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
) 
 518     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 520     if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360; 
 521     if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360; 
 527         DrawEllipse(x
,y
,w
,h
); 
 531     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 535         *m_pstream 
<< "newpath\n" 
 536                << XLOG2DEV(x
+w
/2) << " " << YLOG2DEV(y
+h
/2) << " " 
 537            << XLOG2DEVREL(w
/2) << " " << YLOG2DEVREL(h
/2) << " " 
 538            << int(sa
) <<" "<< int(ea
) << " true ellipticarc\n"; 
 540         CalcBoundingBox( x 
,y 
); 
 541         CalcBoundingBox( x
+w
, y
+h 
); 
 544     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 548         *m_pstream 
<< "newpath\n" 
 549                << XLOG2DEV(x
+w
/2) << " " << YLOG2DEV(y
+h
/2) << " " 
 550            << XLOG2DEVREL(w
/2) << " " << XLOG2DEVREL(h
/2) << " " 
 551            << int(sa
) <<" "<< int(ea
) << " false ellipticarc\n"; 
 553         CalcBoundingBox( x
, y 
); 
 554         CalcBoundingBox( x
+w
, y
+h 
); 
 558 void wxPostScriptDC::DrawPoint (long x
, long y
) 
 560     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 562     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 566     *m_pstream 
<< "newpath\n" 
 567          << XLOG2DEV(x
)   << " " << YLOG2DEV (y
) << " moveto\n" 
 568          << XLOG2DEV(x
+1) << " " << YLOG2DEV (y
) << " lineto\n" 
 571     CalcBoundingBox( x
, y 
); 
 574 void wxPostScriptDC::DrawPolygon (int n
, wxPoint points
[], long xoffset
, long yoffset
, int WXUNUSED(fillStyle
)) 
 576     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 580     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 584     *m_pstream 
<< "newpath\n"; 
 586     long xx 
= XLOG2DEV(points
[0].x 
+ xoffset
); 
 587     long yy 
= YLOG2DEV(points
[0].y 
+ yoffset
); 
 588     *m_pstream 
<< xx 
<< " " << yy 
<< " moveto\n"; 
 589     CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 591     for (int i 
= 1; i 
< n
; i
++) 
 593         xx 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 594         yy 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 595         *m_pstream 
<< xx 
<< " " << yy 
<< " lineto\n"; 
 596         CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 598     *m_pstream 
<< "fill\n"; 
 601     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 605     *m_pstream 
<< "newpath\n"; 
 607     long xx 
= XLOG2DEV(points
[0].x 
+ xoffset
); 
 608     long yy 
= YLOG2DEV(points
[0].y 
+ yoffset
); 
 609     *m_pstream 
<< xx 
<< " " << yy 
<< " moveto\n"; 
 610     CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 612     for (int i 
= 1; i 
< n
; i
++) 
 614         xx 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 615         yy 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 616         *m_pstream 
<< xx 
<< " " << yy 
<< " lineto\n"; 
 617         CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 620     *m_pstream 
<< "stroke\n"; 
 624 void wxPostScriptDC::DrawLines (int n
, wxPoint points
[], long xoffset
, long yoffset
) 
 626     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 628     if (m_pen
.GetStyle() == wxTRANSPARENT
) 
 636     for ( i 
=0; i
<n 
; i
++ ) 
 638         CalcBoundingBox( XLOG2DEV(points
[i
].x
+xoffset
), YLOG2DEV(points
[i
].y
+yoffset
)); 
 641     *m_pstream 
<< "newpath\n" 
 642                << XLOG2DEV(points
[0].x
+xoffset
) << " " 
 643                << YLOG2DEV(points
[0].y
+yoffset
) << " moveto\n"; 
 645     for (i 
= 1; i 
< n
; i
++) 
 647         *m_pstream 
<< XLOG2DEV(points
[i
].x
+xoffset
) << " " 
 648                    << YLOG2DEV(points
[i
].y
+yoffset
) << " lineto\n"; 
 651     *m_pstream 
<< "stroke\n"; 
 654 void wxPostScriptDC::DrawRectangle (long x
, long y
, long width
, long height
) 
 656     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 658     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 662         *m_pstream 
<< "newpath\n" 
 663                    << XLOG2DEV(x
) << " " << YLOG2DEV(y
) << " moveto\n" 
 664                    << XLOG2DEV(x 
+ width
) << " " << YLOG2DEV(y
) << " lineto\n" 
 665                    << XLOG2DEV(x 
+ width
) << " " << YLOG2DEV(y 
+ height
) << " lineto\n" 
 666                    << XLOG2DEV(x
) << " " << YLOG2DEV(y 
+ height
) << " lineto\n" 
 670         CalcBoundingBox( x
, y 
); 
 671         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 674     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 678         *m_pstream 
<< "newpath\n" 
 679                    << XLOG2DEV(x
) << " " << YLOG2DEV(y
) << " moveto\n" 
 680                    << XLOG2DEV(x 
+ width
) << " " << YLOG2DEV(y
) << " lineto\n" 
 681                    << XLOG2DEV(x 
+ width
) << " " << YLOG2DEV(y 
+ height
) << " lineto\n" 
 682                    << XLOG2DEV(x
) << " " << YLOG2DEV(y 
+ height
) << " lineto\n" 
 686         CalcBoundingBox( x
, y 
); 
 687         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 691 void wxPostScriptDC::DrawRoundedRectangle (long x
, long y
, long width
, long height
, double radius
) 
 693     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 697         // Now, a negative radius is interpreted to mean 
 698         // 'the proportion of the smallest X or Y dimension' 
 699         double smallest 
= 0.0; 
 704         radius 
=  (-radius 
* smallest
); 
 707     long rad 
= (long) radius
; 
 709     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 713         // Draw rectangle anticlockwise 
 714         *m_pstream 
<< "newpath\n" 
 715                    << XLOG2DEV(x 
+ rad
) << " " << YLOG2DEV(y 
+ rad
) << " " << XLOG2DEVREL(rad
) << " 90 180 arc\n" 
 716                    << XLOG2DEV(x
) << " " << YLOG2DEV(y 
+ rad
) << " moveto\n" 
 717                    << XLOG2DEV(x 
+ rad
) << " " << YLOG2DEV(y 
+ height 
- rad
) << " " << XLOG2DEVREL(rad
) << " 180 270 arc\n" 
 718                    << XLOG2DEV(x 
+ width 
- rad
) << " " << YLOG2DEV(y 
+ height
) << " lineto\n" 
 719                    << XLOG2DEV(x 
+ width 
- rad
) << " " << YLOG2DEV(y 
+ height 
- rad
) << " " << XLOG2DEVREL(rad
) << " 270 0 arc\n" 
 720                    << XLOG2DEV(x 
+ width
) << " " << YLOG2DEV(y 
+ rad
) << " lineto\n" 
 721                    << XLOG2DEV(x 
+ width 
- rad
) << " " << YLOG2DEV(y 
+ rad
) << " " << XLOG2DEVREL(rad
) << " 0 90 arc\n" 
 722                    << XLOG2DEV(x 
+ rad
) << " " << YLOG2DEV(y
) << " lineto\n" 
 726         CalcBoundingBox( x
, y 
); 
 727         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 730     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 734         // Draw rectangle anticlockwise 
 735         *m_pstream 
<< "newpath\n" 
 736                    << XLOG2DEV(x 
+ rad
) << " " << YLOG2DEV(y 
+ rad
) << " " << XLOG2DEVREL(rad
) << " 90 180 arc\n" 
 737                    << XLOG2DEV(x
) << " " << YLOG2DEV(y 
+ rad
) << " moveto\n" 
 738                    << XLOG2DEV(x 
+ rad
) << " " << YLOG2DEV(y 
+ height 
- rad
) << " " << XLOG2DEVREL(rad
) << " 180 270 arc\n" 
 739                    << XLOG2DEV(x 
+ width 
- rad
) << " " << YLOG2DEV(y 
+ height
) << " lineto\n" 
 740                    << XLOG2DEV(x 
+ width 
- rad
) << " " << YLOG2DEV(y 
+ height 
- rad
) << " " << XLOG2DEVREL(rad
) << " 270 0 arc\n" 
 741                    << XLOG2DEV(x 
+ width
) << " " << YLOG2DEV(y 
+ rad
) << " lineto\n" 
 742                    << XLOG2DEV(x 
+ width 
- rad
) << " " << YLOG2DEV(y 
+ rad
) << " " << XLOG2DEVREL(rad
) << " 0 90 arc\n" 
 743                    << XLOG2DEV(x 
+ rad
) << " " << YLOG2DEV(y
) << " lineto\n" 
 747         CalcBoundingBox( x
, y 
); 
 748         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 752 void wxPostScriptDC::DrawEllipse (long x
, long y
, long width
, long height
) 
 754     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 756     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 760         *m_pstream 
<< "newpath\n" 
 761                    << XLOG2DEV(x 
+ width 
/ 2) << " " << YLOG2DEV(y 
+ height 
/ 2) << " " 
 762                    << XLOG2DEV(width 
/ 2) << " " << YLOG2DEVREL(height 
/ 2) << " 0 360 ellipse\n" 
 765         CalcBoundingBox( x 
- width
, y 
- height 
); 
 766         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 769     if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
) 
 773         *m_pstream 
<< "newpath\n" 
 774                    << XLOG2DEV(x 
+ width 
/ 2) << " " << YLOG2DEV(y 
+ height 
/ 2) << " " 
 775                    << XLOG2DEV(width 
/ 2) << " " << YLOG2DEVREL(height 
/ 2) << " 0 360 ellipse\n" 
 778         CalcBoundingBox( x 
- width
, y 
- height 
); 
 779         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 783 void wxPostScriptDC::DrawIcon( const wxIcon
& icon
, long x
, long y 
) 
 785     DrawBitmap( icon
, x
, y
, TRUE 
); 
 788 void wxPostScriptDC::DrawBitmap( const wxBitmap
& bitmap
, long x
, long y
, bool WXUNUSED(useMask
) ) 
 790     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 792     if (!bitmap
.Ok()) return; 
 794     wxImage 
image( bitmap 
); 
 796     if (!image
.Ok()) return; 
 798     int ww 
= XLOG2DEVREL(image
.GetWidth()); 
 799     int hh 
= YLOG2DEVREL(image
.GetHeight()); 
 801     image 
= image
.Scale( ww
, hh 
); 
 803     if (!image
.Ok()) return; 
 805     int xx 
= XLOG2DEV(x
); 
 806     int yy 
= YLOG2DEV(y 
+ bitmap
.GetHeight()); 
 808     *m_pstream 
<< "/origstate save def\n" 
 810                << "/pix " << ww 
<< " string def\n" 
 811                << "/grays " << ww 
<< " string def\n" 
 812                << "/npixels 0 def\n" 
 813                << "/rgbindx 0 def\n" 
 814                << xx 
<< " " << yy 
<< " translate\n" 
 815                << ww 
<< " " << hh 
<< " scale\n" 
 816                << ww 
<< " " << hh 
<< " 8\n" 
 817                << "[" << ww 
<< " 0 0 " << (-hh
) << " 0 " << hh 
<< "]\n" 
 818                << "{currentfile pix readhexstring pop}\n" 
 819                << "false 3 colorimage\n"; 
 821     for (int j 
= 0; j 
< hh
; j
++) 
 823         for (int i 
= 0; i 
< ww
; i
++) 
 827         wxDecToHex( image
.GetRed(i
,j
), buffer 
); 
 828             *m_pstream 
<< buffer
; 
 829         wxDecToHex( image
.GetGreen(i
,j
), buffer 
); 
 830             *m_pstream 
<< buffer
; 
 831         wxDecToHex( image
.GetBlue(i
,j
), buffer 
); 
 832             *m_pstream 
<< buffer
; 
 837     *m_pstream 
<< "end\n"; 
 838     *m_pstream 
<< "origstate restore\n"; 
 842 void wxPostScriptDC::SetFont( const wxFont
& font 
) 
 844     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 846     if (!font
.Ok())  return; 
 851     const char *style 
= ""; 
 852     int Style 
= m_font
.GetStyle(); 
 853     int Weight 
= m_font
.GetWeight(); 
 855     switch (m_font
.GetFamily ()) 
 865 //          name = "/Times-Roman"; 
 866             name 
= "/Times"; // Altered by EDZ 
 869             name 
= "/Zapf-Chancery-MediumItalic"; 
 874         case wxDEFAULT
: // Sans Serif Font 
 875             name 
= "/LucidaSans"; 
 878     if (Style 
== wxNORMAL 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 880       if (m_font
.GetFamily () == wxROMAN
) 
 885     else if (Style 
== wxNORMAL 
&& Weight 
== wxBOLD
) 
 889     else if (Style 
== wxITALIC 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 891       if (m_font
.GetFamily () == wxROMAN
) 
 896     else if (Style 
== wxITALIC 
&& Weight 
== wxBOLD
) 
 898       if (m_font
.GetFamily () == wxROMAN
) 
 899     style 
= "-BoldItalic"; 
 901     style 
= "-BoldOblique"; 
 903     else if (Style 
== wxSLANT 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 905       if (m_font
.GetFamily () == wxROMAN
) 
 910     else if (Style 
== wxSLANT 
&& Weight 
== wxBOLD
) 
 912       if (m_font
.GetFamily () == wxROMAN
) 
 913     style 
= "-BoldItalic"; 
 915     style 
= "-BoldOblique"; 
 926     *m_pstream 
<< buf 
<< " reencodeISO def\n"; 
 927     *m_pstream 
<< buf 
<< " findfont\n"; 
 928     *m_pstream 
<< YLOG2DEVREL(m_font
.GetPointSize()) << " scalefont setfont\n"; 
 931 void wxPostScriptDC::SetPen( const wxPen
& pen 
) 
 933     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
 935     if (!pen
.Ok()) return; 
 937     int oldStyle 
= m_pen
.GetStyle(); 
 941     *m_pstream 
<< XLOG2DEVREL(m_pen
.GetWidth()) << " setlinewidth\n"; 
 944      Line style - WRONG: 2nd arg is OFFSET 
 946      Here, I'm afraid you do not conceive meaning of parameters of 'setdash' 
 947      operator correctly. You should look-up this in the Red Book: the 2nd parame- 
 948      ter is not number of values in the array of the first one, but an offset 
 949      into this description of the pattern. I mean a real *offset* not index 
 950      into array. I.e. If the command is [3 4] 1 setdash   is used, then there 
 951      will be first black line *2* units long, then space 4 units, then the 
 952      pattern of *3* units black, 4 units space will be repeated. 
 955     static const char *dotted 
= "[2 5] 2"; 
 956     static const char *short_dashed 
= "[4 4] 2"; 
 957     static const char *long_dashed 
= "[4 8] 2"; 
 958     static const char *dotted_dashed 
= "[6 6 2 6] 4"; 
 960     const char *psdash 
= (char *) NULL
; 
 961     switch (m_pen
.GetStyle ()) 
 963         case wxDOT
:           psdash 
= dotted
;         break; 
 964         case wxSHORT_DASH
:    psdash 
= short_dashed
;   break; 
 965         case wxLONG_DASH
:     psdash 
= long_dashed
;    break; 
 966         case wxDOT_DASH
:      psdash 
= dotted_dashed
;  break; 
 969         default:              psdash 
= "[] 0";         break; 
 972     if (oldStyle 
!= m_pen
.GetStyle()) 
 974         *m_pstream 
<< psdash 
<< " setdash\n"; 
 978     unsigned char red 
= m_pen
.GetColour().Red(); 
 979     unsigned char blue 
= m_pen
.GetColour().Blue(); 
 980     unsigned char green 
= m_pen
.GetColour().Green(); 
 984         // Anything not white is black 
 985         if (!(red 
== (unsigned char) 255 && blue 
== (unsigned char) 255 
 986         && green 
== (unsigned char) 255)) 
 988         red 
= (unsigned char) 0; 
 989         green 
= (unsigned char) 0; 
 990         blue 
= (unsigned char) 0; 
 996     if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
 998        float redPS 
= (float)(red
) / 255.0; 
 999        float bluePS 
= (float)(blue
) / 255.0; 
1000        float greenPS 
= (float)(green
) / 255.0; 
1001        *m_pstream 
<< redPS 
<< " " << greenPS 
<< " " << bluePS 
<< " setrgbcolor\n"; 
1004        m_currentBlue 
= blue
; 
1005        m_currentGreen 
= green
; 
1009 void wxPostScriptDC::SetBrush( const wxBrush
& brush 
) 
1011     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
1013     if (!brush
.Ok()) return; 
1018     unsigned char red 
= m_brush
.GetColour().Red(); 
1019     unsigned char blue 
= m_brush
.GetColour().Blue(); 
1020     unsigned char green 
= m_brush
.GetColour().Green(); 
1024         // Anything not black is white 
1025         if (!(red 
== (unsigned char) 0 && blue 
== (unsigned char) 0 
1026         && green 
== (unsigned char) 0)) 
1028         red 
= (unsigned char) 255; 
1029         green 
= (unsigned char) 255; 
1030         blue 
= (unsigned char) 255; 
1036     if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1038        float redPS 
= (float)(red
) / 255.0; 
1039        float bluePS 
= (float)(blue
) / 255.0; 
1040        float greenPS 
= (float)(green
) / 255.0; 
1041        *m_pstream 
<< redPS 
<< " " << greenPS 
<< " " << bluePS 
<< " setrgbcolor\n"; 
1043        m_currentBlue 
= blue
; 
1044        m_currentGreen 
= green
; 
1048 void wxPostScriptDC::DrawText( const wxString
& text
, long x
, long y
, bool WXUNUSED(use16bit
) ) 
1050     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
1054     if (m_textForegroundColour
.Ok ()) 
1056         unsigned char red 
= m_textForegroundColour
.Red (); 
1057         unsigned char blue 
= m_textForegroundColour
.Blue (); 
1058         unsigned char green 
= m_textForegroundColour
.Green (); 
1062       // Anything not white is black 
1063       if (!(red 
== (unsigned char) 255 && blue 
== (unsigned char) 255 
1064         && green 
== (unsigned char) 255)) 
1066           red 
= (unsigned char) 0; 
1067           green 
= (unsigned char) 0; 
1068           blue 
= (unsigned char) 0; 
1072     // maybe setgray here ? 
1074         if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1076             float redPS 
= (float)(red
) / 255.0; 
1077             float bluePS 
= (float)(blue
) / 255.0; 
1078             float greenPS 
= (float)(green
) / 255.0; 
1079             *m_pstream 
<< redPS 
<< " " << greenPS 
<< " " << bluePS 
<< " setrgbcolor\n"; 
1082             m_currentBlue 
= blue
; 
1083             m_currentGreen 
= green
; 
1087     int size 
= m_font
.GetPointSize(); 
1089     long by 
= y 
+ (long)floor( float(size
) * 2.0 / 3.0 ); // approximate baseline 
1090     *m_pstream 
<< XLOG2DEV(x
) << " " << YLOG2DEV(by
) << " moveto\n"; 
1093     int len 
= strlen ((char *)(const char *)text
); 
1095     for (i 
= 0; i 
< len
; i
++) 
1097         int c 
= (unsigned char) text
[i
]; 
1098         if ( c 
== ')' || c 
== '(' || c 
== '\\') 
1100             *m_pstream 
<< "\\" << (char) c
; 
1102         else if ( c 
>= 128 ) 
1104             // Cope with character codes > 127 
1106             sprintf(tmp
, "\\%o", c
); 
1110             *m_pstream 
<< (char) c
; 
1113     *m_pstream 
<< ")" << " show\n"; 
1115     if (m_font
.GetUnderlined()) 
1117         long uy 
= (long)(y 
+ size 
- m_underlinePosition
); 
1119         GetTextExtent(text
, &w
, &h
); 
1121         *m_pstream 
<< "gsave " << XLOG2DEV(x
) << " " << YLOG2DEV(uy
) 
1123                    << (long)m_underlineThickness 
<< " setlinewidth " 
1124                    << XLOG2DEV(x 
+ w
) << " " << YLOG2DEV(uy
) 
1125                    << " lineto stroke grestore\n"; 
1128     CalcBoundingBox( x
, y 
); 
1129     CalcBoundingBox( x 
+ size 
* text
.Length() * 2/3 , y 
); 
1133 void wxPostScriptDC::SetBackground (const wxBrush
& brush
) 
1135     m_backgroundBrush 
= brush
; 
1138 void wxPostScriptDC::SetLogicalFunction (int WXUNUSED(function
)) 
1140     wxFAIL_MSG( "wxPostScriptDC::SetLogicalFunction not implemented." ); 
1143 void wxPostScriptDC::DrawSpline( wxList 
*points 
) 
1145     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
1149     double a
, b
, c
, d
, x1
, y1
, x2
, y2
, x3
, y3
; 
1152     wxNode 
*node 
= points
->First(); 
1153     p 
= (wxPoint 
*)node
->Data(); 
1157     node 
= node
->Next(); 
1158     p 
= (wxPoint 
*)node
->Data(); 
1161     x3 
= a 
= (double)(x1 
+ c
) / 2; 
1162     y3 
= b 
= (double)(y1 
+ d
) / 2; 
1164     *m_pstream  
<< "newpath " 
1165                 << XLOG2DEV((long)x1
) << " " << YLOG2DEV((long)y1
) << " moveto " 
1166         << XLOG2DEV((long)x3
) << " " << YLOG2DEV((long)y3
) << " lineto\n"; 
1168     CalcBoundingBox( (long)x1
, (long)y1 
); 
1169     CalcBoundingBox( (long)x3
, (long)y3 
); 
1171     while ((node 
= node
->Next()) != NULL
) 
1173         q 
= (wxPoint 
*)node
->Data(); 
1181         x3 
= (double)(x2 
+ c
) / 2; 
1182         y3 
= (double)(y2 
+ d
) / 2; 
1183         *m_pstream 
<< XLOG2DEV((long)x1
) << " " << YLOG2DEV((long)y1
) << " " 
1184                << XLOG2DEV((long)x2
) << " " << YLOG2DEV((long)y2
) << " " 
1185                    << XLOG2DEV((long)x3
) << " " << YLOG2DEV((long)y3
) << " DrawSplineSection\n"; 
1187         CalcBoundingBox( (long)x1
, (long)y1 
); 
1188         CalcBoundingBox( (long)x3
, (long)y3 
); 
1192      At this point, (x2,y2) and (c,d) are the position of the 
1193      next-to-last and last point respectively, in the point list 
1196     *m_pstream 
<< XLOG2DEV((long)c
) << " " << YLOG2DEV((long)d
) << " lineto stroke\n"; 
1199 long wxPostScriptDC::GetCharWidth () 
1201     // Chris Breeze: reasonable approximation using wxMODERN/Courier 
1202     return (long) (GetCharHeight() * 72.0 / 120.0); 
1206 void wxPostScriptDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
1208     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
1210     m_signX 
= (xLeftRight 
? 1 : -1); 
1211     m_signY 
= (yBottomUp  
? 1 : -1); 
1213     // FIXME there is no such function in MSW 
1215     ComputeScaleAndOrigin(); 
1219 void wxPostScriptDC::SetDeviceOrigin( long x
, long y 
) 
1221     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
1227     wxDC::SetDeviceOrigin( x
, h
-y 
); 
1230 void wxPostScriptDC::GetSize(int* width
, int* height
) const 
1232     wxPaperSize id 
= m_printData
.GetPaperId(); 
1234     wxPrintPaperType 
*paper 
= wxThePrintPaperDatabase
->FindPaperType(id
); 
1236     if (!paper
) paper 
= wxThePrintPaperDatabase
->FindPaperType(wxPAPER_A4
); 
1240         if (width
) *width 
= paper
->GetSizeDeviceUnits().x
; 
1241         if (height
) *height 
= paper
->GetSizeDeviceUnits().y
; 
1245         if (width
) *width 
= 595; 
1246         if (height
) *height 
= 842; 
1250 void wxPostScriptDC::GetSizeMM(int *width
, int *height
) const 
1252     wxPaperSize id 
= m_printData
.GetPaperId(); 
1254     wxPrintPaperType 
*paper 
= wxThePrintPaperDatabase
->FindPaperType(id
); 
1256     if (!paper
) paper 
= wxThePrintPaperDatabase
->FindPaperType(wxPAPER_A4
); 
1260         if (width
) *width 
= paper
->GetWidth() / 10; 
1261         if (height
) *height 
= paper
->GetHeight() / 10; 
1265        if (width
) *width 
= 210; 
1266        if (height
) *height 
= 297; 
1270 // Resolution in pixels per logical inch 
1271 wxSize 
wxPostScriptDC::GetPPI(void) const 
1273     return wxSize(72, 72); 
1277 bool wxPostScriptDC::StartDoc (const wxString
& message
) 
1279     wxCHECK_MSG( m_ok
, FALSE
, "invalid postscript dc" ); 
1281     if (m_printData
.GetFilename() == "") 
1283         wxString filename 
= wxGetTempFileName("ps"); 
1284         m_printData
.SetFilename(filename
); 
1289     m_pstream 
= new ofstream (m_printData
.GetFilename()); 
1291     if (!m_pstream 
|| !m_pstream
->good()) 
1293         wxMessageBox (_("Cannot open file!"), _("Error"), wxOK
); 
1300     SetBrush( *wxBLACK_BRUSH 
); 
1301     SetPen( *wxBLACK_PEN 
); 
1302     SetBackground( *wxWHITE_BRUSH 
); 
1303     SetTextForeground( *wxBLACK 
); 
1305     // set origin according to paper size 
1306     SetDeviceOrigin( 0,0 ); 
1314 void wxPostScriptDC::EndDoc () 
1316     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
1321         *m_pstream 
<< "grestore\n"; 
1327         m_pstream 
= (ofstream 
*) NULL
; 
1330     char *header_file 
= wxGetTempFileName("ps"); 
1332     m_pstream 
= new ofstream( header_file 
); 
1334     *m_pstream 
<< "%!PS-Adobe-2.0\n";   /* PostScript magic strings */ 
1335     *m_pstream 
<< "%%Title: " << (const char *) m_title 
<< "\n"; 
1336     *m_pstream 
<< "%%Creator: " << wxTheApp
->argv
[0] << "\n"; 
1337     *m_pstream 
<< "%%CreationDate: " << wxNow() << "\n"; 
1340     if ( wxGetEmailAddress(userID
, sizeof(userID
)) ) 
1342         *m_pstream 
<< "%%For: " << (char *)userID
; 
1344         if (wxGetUserName(userName
, sizeof(userName
))) 
1345             *m_pstream 
<< " (" << (char *)userName 
<< ")"; 
1348     else if ( wxGetUserName(userID
, sizeof(userID
)) ) 
1350         *m_pstream 
<< "%%For: " << (char *)userID 
<< "\n"; 
1353     // THE FOLLOWING HAS BEEN CONTRIBUTED BY Andy Fyfe <andy@hyperparallel.com> 
1355     long wx_printer_translate_x
, wx_printer_translate_y
; 
1356     double wx_printer_scale_x
, wx_printer_scale_y
; 
1358     wx_printer_translate_x 
= m_printData
.GetPrinterTranslateX(); 
1359     wx_printer_translate_y 
= m_printData
.GetPrinterTranslateY(); 
1361     wx_printer_scale_x 
= m_printData
.GetPrinterScaleX(); 
1362     wx_printer_scale_y 
= m_printData
.GetPrinterScaleY(); 
1364     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1366         *m_pstream 
<< "%%Orientation: Landscape\n"; 
1370         *m_pstream 
<< "%%Orientation: Portrait\n"; 
1373     // Compute the bounding box.  Note that it is in the default user 
1374     // coordinate system, thus we have to convert the values. 
1375     long llx 
= (long) ((XLOG2DEV(m_minX
)+wx_printer_translate_x
)*wx_printer_scale_x
); 
1376     long lly 
= (long) ((YLOG2DEV(m_minY
)+wx_printer_translate_y
)*wx_printer_scale_y
); 
1377     long urx 
= (long) ((XLOG2DEV(m_maxX
)+wx_printer_translate_x
)*wx_printer_scale_x
); 
1378     long ury 
= (long) ((YLOG2DEV(m_maxY
)+wx_printer_translate_y
)*wx_printer_scale_y
); 
1380     // If we're landscape, our sense of "x" and "y" is reversed. 
1381     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1384         tmp 
= llx
; llx 
= lly
; lly 
= tmp
; 
1385         tmp 
= urx
; urx 
= ury
; ury 
= tmp
; 
1387         // We need either the two lines that follow, or we need to subtract 
1388         // min_x from real_translate_y, which is commented out below. 
1389         llx 
= llx 
- (long)(m_minX
*wx_printer_scale_y
); 
1390         urx 
= urx 
- (long)(m_minX
*wx_printer_scale_y
); 
1393     // The Adobe specifications call for integers; we round as to make 
1394     // the bounding larger. 
1395     *m_pstream 
<< "%%BoundingBox: " 
1396                << floor((double)llx
) << " " << floor((double)lly
) << " " 
1397                << ceil((double)urx
)  << " " << ceil((double)ury
)  << "\n"; 
1398     *m_pstream 
<< "%%Pages: " << (wxPageNumber 
- 1) << "\n"; 
1399     *m_pstream 
<< "%%EndComments\n\n"; 
1401     // To check the correctness of the bounding box, postscript commands 
1402     // to draw a box corresponding to the bounding box are generated below. 
1403     // But since we typically don't want to print such a box, the postscript 
1404     // commands are generated within comments.  These lines appear before any 
1405     // adjustment of scale, rotation, or translation, and hence are in the 
1406     // default user coordinates. 
1407     *m_pstream 
<< "% newpath\n"; 
1408     *m_pstream 
<< "% " << llx 
<< " " << lly 
<< " moveto\n"; 
1409     *m_pstream 
<< "% " << urx 
<< " " << lly 
<< " lineto\n"; 
1410     *m_pstream 
<< "% " << urx 
<< " " << ury 
<< " lineto\n"; 
1411     *m_pstream 
<< "% " << llx 
<< " " << ury 
<< " lineto closepath stroke\n"; 
1413     *m_pstream 
<< "%%BeginProlog\n"; 
1414     *m_pstream 
<< wxPostScriptHeaderEllipse
; 
1415     *m_pstream 
<< wxPostScriptHeaderEllipticArc
; 
1416     *m_pstream 
<< wxPostScriptHeaderColourImage
; 
1417     *m_pstream 
<< wxPostScriptHeaderReencodeISO1
; 
1418     *m_pstream 
<< wxPostScriptHeaderReencodeISO2
; 
1420     if (wxPostScriptHeaderSpline
) 
1421         *m_pstream 
<< wxPostScriptHeaderSpline
; 
1422     *m_pstream 
<< "%%EndProlog\n"; 
1425     m_pstream 
= (ofstream 
*) NULL
; 
1427     char *tmp_file 
= wxGetTempFileName("ps"); 
1429     // Paste header Before wx_printer_file 
1430     wxConcatFiles (header_file
, m_printData
.GetFilename(), tmp_file
); 
1431     wxRemoveFile (header_file
); 
1432     wxRemoveFile (m_printData
.GetFilename()); 
1433     wxRenameFile(tmp_file
, m_printData
.GetFilename()); 
1435 #if defined(__X__) || defined(__WXGTK__) 
1438       wxString 
previewCommand(m_printData
.GetPreviewCommand()); 
1439       wxString 
printerCommand(m_printData
.GetPrinterCommand()); 
1440       wxString 
printerOptions(m_printData
.GetPrinterOptions()); 
1441       wxString 
filename(m_printData
.GetFilename()); 
1443       switch (m_printData
.GetPrintMode()) { 
1445     case wxPRINT_MODE_PREVIEW
: 
1448           argv
[0] = (char*) (const char*) previewCommand
; 
1449           argv
[1] = (char*) (const char*) filename
; 
1450           argv
[2] = (char*) (char *) NULL
; 
1451           wxExecute (argv
, TRUE
); 
1452           wxRemoveFile(m_printData
.GetFilename()); 
1456     case wxPRINT_MODE_PRINTER
: 
1460           argv
[argc
++] = (char*) (const char*) printerCommand
; 
1462           // !SM! If we simply assign to argv[1] here, if printer options 
1463           // are blank, we get an annoying and confusing message from lpr. 
1464           char * opts 
= (char*) (const char*) printerOptions
; 
1466               argv
[argc
++] = opts
; 
1468           argv
[argc
++] = (char*) (const char*) filename
; 
1469           argv
[argc
++] = (char *) NULL
; 
1470           wxExecute (argv
, TRUE
); 
1471           wxRemoveFile(filename
); 
1475     case wxPRINT_MODE_FILE
: 
1476     case wxPRINT_MODE_NONE
: 
1483 void wxPostScriptDC::StartPage () 
1485     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
1487     *m_pstream 
<< "%%Page: " << (wxPageNumber
++) << "\n"; 
1489 //  *m_pstream << "matrix currentmatrix\n"; 
1491     // Added by Chris Breeze 
1493     // Each page starts with an "initgraphics" which resets the 
1494     // transformation and so we need to reset the origin 
1495     // (and rotate the page for landscape printing) 
1498     m_scaleFactor = 1.0; 
1499     m_logicalOriginX = 0; 
1500     m_logicalOriginY = 0; 
1503     long translate_x
, translate_y
; 
1504     double scale_x
, scale_y
; 
1506     translate_x 
= m_printData
.GetPrinterTranslateX(); 
1507     translate_y 
= m_printData
.GetPrinterTranslateY(); 
1509     scale_x 
= m_printData
.GetPrinterScaleX(); 
1510     scale_y 
= m_printData
.GetPrinterScaleY(); 
1512     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1514         translate_y 
-= m_maxY
; 
1515         *m_pstream 
<< "90 rotate\n"; 
1518     *m_pstream 
<< scale_x 
<< " " << scale_y 
<< " scale\n"; 
1519     *m_pstream 
<< translate_x 
<< " " << translate_y 
<< " translate\n"; 
1522 void wxPostScriptDC::EndPage () 
1524     wxCHECK_RET( m_ok 
&& m_pstream
, "invalid postscript dc" ); 
1526     *m_pstream 
<< "showpage\n"; 
1529 bool wxPostScriptDC::Blit( long xdest
, long ydest
, 
1530                            long fwidth
, long fheight
, 
1532                            long xsrc
, long ysrc
, 
1533                            int rop
, bool WXUNUSED(useMask
) ) 
1535     wxCHECK_MSG( m_ok 
&& m_pstream
, FALSE
, "invalid postscript dc" ); 
1537     wxCHECK_MSG( source
, FALSE
, "invalid source dc" ); 
1539     /* blit into a bitmap */ 
1541     wxBitmap 
bitmap( (int)fwidth
, (int)fheight 
); 
1543     memDC
.SelectObject(bitmap
); 
1544     memDC
.Blit(0, 0, fwidth
, fheight
, source
, xsrc
, ysrc
, rop
); /* TODO: Blit transparently? */ 
1545     memDC
.SelectObject(wxNullBitmap
); 
1547     /* draw bitmap. scaling and positioning is done there */ 
1549     DrawBitmap( bitmap
, xdest
, ydest 
); 
1554 long wxPostScriptDC::GetCharHeight() 
1557         return  m_font
.GetPointSize(); 
1562 void wxPostScriptDC::GetTextExtent( const wxString
& string
, long *x
, long *y
, 
1563                                     long *descent
, long *externalLeading
, wxFont 
*theFont
, 
1564                                     bool WXUNUSED(use16
) ) 
1566     wxFont 
*fontToUse 
= theFont
; 
1568     if (!fontToUse
) fontToUse 
= (wxFont
*) &m_font
; 
1570     wxCHECK_RET( fontToUse
, "GetTextExtent: no font defined" ); 
1571     wxCHECK_RET( x
, "GetTextExtent: x == NULL" ); 
1572     wxCHECK_RET( y
, "GetTextExtent: y == NULL" ); 
1574 #if !USE_AFM_FOR_POSTSCRIPT 
1575     /* Provide a VERY rough estimate (avoid using it). 
1576      * Produces accurate results for mono-spaced font 
1577      * such as Courier (aka wxMODERN) */ 
1582         height 
= fontToUse
->GetPointSize(); 
1584     *x 
= strlen (string
) * height 
* 72 / 120; 
1585     *y 
= (long) (height 
* 1.32);    /* allow for descender */ 
1586     if (descent
) *descent 
= 0; 
1587     if (externalLeading
) *externalLeading 
= 0; 
1590     /* method for calculating string widths in postscript: 
1591     /  read in the AFM (adobe font metrics) file for the 
1592     /  actual font, parse it and extract the character widths 
1593     /  and also the descender. this may be improved, but for now 
1594     /  it works well. the AFM file is only read in if the 
1595     /  font is changed. this may be chached in the future. 
1596     /  calls to GetTextExtent with the font unchanged are rather 
1599     /  for each font and style used there is an AFM file necessary. 
1600     /  currently i have only files for the roman font family. 
1601     /  I try to get files for the other ones! 
1603     /  CAVE: the size of the string is currently always calculated 
1604     /        in 'points' (1/72 of an inch). this should later on be 
1605     /        changed to depend on the mapping mode. 
1606     /  CAVE: the path to the AFM files must be set before calling this 
1607     /        function. this is usually done by a call like the following: 
1608     /        wxSetAFMPath("d:\\wxw161\\afm\\"); 
1612     /    wxPostScriptDC dc(NULL, TRUE); 
1614     /      wxSetAFMPath("d:\\wxw161\\afm\\"); 
1615     /      dc.StartDoc("Test"); 
1618     /      dc.SetFont(new wxFont(10, wxROMAN, wxNORMAL, wxNORMAL)); 
1619     /      dc.GetTextExtent("Hallo",&w,&h); 
1624     /  by steve (stefan.hammes@urz.uni-heidelberg.de) 
1626     /  updated: 14.05.95 */ 
1628     /* these static vars are for storing the state between calls */ 
1629     static int lastFamily
= INT_MIN
; 
1630     static int lastSize
= INT_MIN
; 
1631     static int lastStyle
= INT_MIN
; 
1632     static int lastWeight
= INT_MIN
; 
1633     static int lastDescender 
= INT_MIN
; 
1634     static int lastWidths
[256]; /* widths of the characters */ 
1636     /* get actual parameters */ 
1637     const int Family 
= fontToUse
->GetFamily(); 
1638     const int Size 
=   fontToUse
->GetPointSize(); 
1639     const int Style 
=  fontToUse
->GetStyle(); 
1640     const int Weight 
= fontToUse
->GetWeight(); 
1642     /* if we have another font, read the font-metrics */ 
1643     if (Family
!=lastFamily 
|| Size
!=lastSize 
|| Style
!=lastStyle 
|| Weight
!=lastWeight
) 
1645         /* store actual values */ 
1646         lastFamily 
= Family
; 
1649         lastWeight 
= Weight
; 
1651         char *name 
= (char*) NULL
; 
1657                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "CourBoO"; 
1658                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "CourBo"; 
1659                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "Cour0"; 
1665                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "TimesBoO"; 
1666                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "TimesBo"; 
1667                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "TimesO"; 
1668                     else if name 
= "TimesRo";  /* no typo */ 
1673                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "HelvBoO"; 
1674                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "HelvBo"; 
1675                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "Helv0"; 
1681         /* get the directory of the AFM files */ 
1684         wxString 
fmPath(m_printData
.GetFontMetricPath()); 
1685         if (fmPath 
!= "") strcpy( afmName
, (const char*) fmPath 
); 
1687         /* 2. open and process the file 
1688            /  a short explanation of the AFM format: 
1689            /  we have for each character a line, which gives its size 
1692            /    C 63 ; WX 444 ; N question ; B 49 -14 395 676 ; 
1694            /  that means, we have a character with ascii code 63, and width 
1695            /  (444/1000 * fontSize) points. 
1696            /  the other data is ignored for now! 
1698            /  when the font has changed, we read in the right AFM file and store the 
1699            /  character widths in an array, which is processed below (see point 3.). */ 
1701         /* new elements JC Sun Aug 25 23:21:44 MET DST 1996 */ 
1703         strcat(afmName
,name
); 
1704         strcat(afmName
,".afm"); 
1705         FILE *afmFile 
= fopen(afmName
,"r"); 
1706         if ( afmFile
==NULL 
) 
1708             wxLogDebug( "GetTextExtent: can't open AFM file '%s'\n", afmName 
); 
1709             wxLogDebug( "               using approximate values\n"); 
1710             for (int i
=0; i
<256; i
++) lastWidths
[i
] = 500; /* an approximate value */ 
1711             lastDescender 
= -150; /* dito. */ 
1715             /* init the widths array */ 
1716             for(int i
=0; i
<256; i
++) lastWidths
[i
] = INT_MIN
; 
1717             /* some variables for holding parts of a line */ 
1718             char cString
[10],semiString
[10],WXString
[10],descString
[20]; 
1719             char upString
[30], utString
[30], encString
[50]; 
1722             /* read in the file and parse it */ 
1723             while(fgets(line
,sizeof(line
),afmFile
)!=NULL
) 
1725                 /* A.) check for descender definition */ 
1726                 if (strncmp(line
,"Descender",9)==0) 
1728                     if ((sscanf(line
,"%s%d",descString
,&lastDescender
)!=2) || 
1729                             (strcmp(descString
,"Descender")!=0)) 
1731                         wxLogDebug( "AFM-file '%s': line '%s' has error (bad descender)\n", afmName
,line 
); 
1734                 /* JC 1.) check for UnderlinePosition */ 
1735                 else if(strncmp(line
,"UnderlinePosition",17)==0) 
1737                     if ((sscanf(line
,"%s%lf",upString
,&UnderlinePosition
)!=2) || 
1738                             (strcmp(upString
,"UnderlinePosition")!=0)) 
1740                         wxLogDebug( "AFM-file '%s': line '%s' has error (bad UnderlinePosition)\n", afmName
, line 
); 
1743                 /* JC 2.) check for UnderlineThickness */ 
1744                 else if(strncmp(line
,"UnderlineThickness",18)==0) 
1746                     if ((sscanf(line
,"%s%lf",utString
,&UnderlineThickness
)!=2) || 
1747                             (strcmp(utString
,"UnderlineThickness")!=0)) 
1749                         wxLogDebug( "AFM-file '%s': line '%s' has error (bad UnderlineThickness)\n", afmName
, line 
); 
1752                 /* JC 3.) check for EncodingScheme */ 
1753                 else if(strncmp(line
,"EncodingScheme",14)==0) 
1755                     if ((sscanf(line
,"%s%s",utString
,encString
)!=2) || 
1756                             (strcmp(utString
,"EncodingScheme")!=0)) 
1758                         wxLogDebug("AFM-file '%s': line '%s' has error (bad EncodingScheme)\n", afmName
, line 
); 
1760                     else if (strncmp(encString
, "AdobeStandardEncoding", 21)) 
1762                         wxLogDebug( "AFM-file '%s': line '%s' has error (unsupported EncodingScheme %s)\n", 
1763                                 afmName
,line
, encString
); 
1766                 /* B.) check for char-width */ 
1767                 else if(strncmp(line
,"C ",2)==0) 
1769                     if (sscanf(line
,"%s%d%s%s%d",cString
,&ascii
,semiString
,WXString
,&cWidth
)!=5) 
1771                         wxLogDebug("AFM-file '%s': line '%s' has an error (bad character width)\n",afmName
,line
); 
1773                     if(strcmp(cString
,"C")!=0 || strcmp(semiString
,";")!=0 || strcmp(WXString
,"WX")!=0) 
1775                         wxLogDebug("AFM-file '%s': line '%s' has a format error\n",afmName
,line
); 
1777                     /* printf("            char '%c'=%d has width '%d'\n",ascii,ascii,cWidth); */ 
1778                     if (ascii
>=0 && ascii
<256) 
1780                         lastWidths
[ascii
] = cWidth
; /* store width */ 
1784                         /* MATTHEW: this happens a lot; don't print an error */ 
1785                         /* wxLogDebug("AFM-file '%s': ASCII value %d out of range\n",afmName,ascii); */ 
1788                 /* C.) ignore other entries. */ 
1792         /* hack to compute correct values for german 'Umlaute' 
1793            /  the correct way would be to map the character names 
1794            /  like 'adieresis' to corresp. positions of ISOEnc and read 
1795            /  these values from AFM files, too. Maybe later ... */ 
1796         lastWidths
[196] = lastWidths
['A'];  // Ä 
1797         lastWidths
[228] = lastWidths
['a'];  // ä 
1798         lastWidths
[214] = lastWidths
['O'];  // Ö 
1799         lastWidths
[246] = lastWidths
['o'];  // ö 
1800         lastWidths
[220] = lastWidths
['U'];  // Ü 
1801         lastWidths
[252] = lastWidths
['u'];  // ü 
1802         lastWidths
[223] = lastWidths
[251];  // ß 
1805     /* JC: calculate UnderlineThickness/UnderlinePosition */ 
1806     m_underlinePosition 
= m_underlinePosition 
* fontToUse
->GetPointSize() / 1000.0f
; 
1807     m_underlineThickness 
= m_underlineThickness 
* fontToUse
->GetPointSize() / 1000.0f 
* m_scaleFactor
; 
1809     /* 3. now the font metrics are read in, calc size this 
1810        /  is done by adding the widths of the characters in the 
1811        /  string. they are given in 1/1000 of the size! */ 
1814     long height
=Size
; /* by default */ 
1816     for(p
=(unsigned char *)(const char *)string
; *p
; p
++) 
1818         if(lastWidths
[*p
]== INT_MIN
) 
1820             wxLogDebug("GetTextExtent: undefined width for character '%c' (%d)\n", *p
,*p
); 
1821             widthSum 
+= (long)(lastWidths
[' ']/1000.0F 
* Size
); /* assume space */ 
1825             widthSum 
+= (long)((lastWidths
[*p
]/1000.0F
)*Size
); 
1829     /* add descender to height (it is usually a negative value) */ 
1830     if (lastDescender
!=INT_MIN
) 
1832         height 
+= (long)(((-lastDescender
)/1000.0F
) * Size
); /* MATTHEW: forgot scale */ 
1835     /* return size values */ 
1839     /* return other parameters */ 
1842         if(lastDescender
!=INT_MIN
) 
1844             *descent 
= (long)(((-lastDescender
)/1000.0F
) * Size
); /* MATTHEW: forgot scale */ 
1852     /* currently no idea how to calculate this! */ 
1853     if (externalLeading
) *externalLeading 
= 0; 
1858 // Determine the Default Postscript Previewer 
1859 // available on the platform 
1860 #if defined(__SUN__) && defined(__XVIEW__) 
1861 // OpenWindow/NeWS's Postscript Previewer 
1862 # define PS_VIEWER_PROG "pageview" 
1863 #elif defined(__VMS__) 
1864 #define PS_VIEWER_PROG "view/format=ps/select=x_display" 
1865 #elif defined(__SGI__) 
1866 // SGI's Display Postscript Previewer 
1867 //# define PS_VIEWER_PROG "dps" 
1868 # define PS_VIEWER_PROG "xpsview" 
1869 #elif defined(__X__) || defined(__WXGTK__) 
1870 // Front-end to ghostscript 
1871 # define PS_VIEWER_PROG "ghostview" 
1873 // Windows ghostscript/ghostview 
1874 # define PS_VIEWER_PROG NULL 
1877 wxPrintSetupData 
*wxThePrintSetupData 
= (wxPrintSetupData 
*) NULL
; 
1879 #if !USE_SHARED_LIBRARY 
1880 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptDC
, wxDC
) 
1881 IMPLEMENT_DYNAMIC_CLASS(wxPrintSetupData
, wxObject
) 
1884 // Redundant now I think 
1886 IMPLEMENT_CLASS(wxPostScriptPrintDialog
, wxDialog
) 
1888 wxPostScriptPrintDialog::wxPostScriptPrintDialog (wxWindow 
*parent
, const wxString
& title
, 
1889             const wxPoint
& pos
, const wxSize
& size
, long style
): 
1890    wxDialog(parent
, -1, title
, pos
, size
, style
) 
1892    wxBeginBusyCursor(); 
1897       *orientation 
= new wxString
[2], 
1898       *print_modes 
= new wxString
[3]; 
1900    long wx_printer_translate_x
, wx_printer_translate_y
; 
1901    double wx_printer_scale_x
, wx_printer_scale_y
; 
1903    orientation
[0] = _("Portrait"); 
1904    orientation
[1] = _("Landscape"); 
1906    print_modes
[0] = _("Send to Printer"); 
1907    print_modes
[1] = _("Print to File"); 
1908    print_modes
[2] = _("Preview Only"); 
1912    wxButton 
*okBut 
= new wxButton (this, wxID_OK
, _("OK"), wxPoint(5, 5)); 
1913    (void) new wxButton (this, wxID_CANCEL
, _("Cancel"), wxPoint(40, 5)); 
1914    okBut
->SetDefault(); 
1917 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1918    (void) new wxStaticText( this, -1, _("Printer Command: "), 
1920    (void) new wxTextCtrl( this, wxID_PRINTER_COMMAND
, wxThePrintSetupData
->GetPrinterCommand(), 
1921                           wxPoint(100, yPos
), wxSize(100, -1) ); 
1923    (void) new wxStaticText( this, -1, _("Printer Options: "), 
1924                             wxPoint(210, yPos
) ); 
1925    (void) new wxTextCtrl( this, wxID_PRINTER_OPTIONS
, wxThePrintSetupData
->GetPrinterOptions(), 
1926                           wxPoint(305, yPos
), wxSize(150, -1) ); 
1932    wxRadioBox 
*radio0 
= new wxRadioBox(this, wxID_PRINTER_ORIENTATION
, "Orientation: ", wxPoint(5, yPos
), wxSize(-1,-1), 
1933                                        2,orientation
,2,wxRA_SPECIFY_ROWS
); 
1934    radio0
->SetSelection((int)wxThePrintSetupData
->GetPrinterOrientation() - 1); 
1936   // @@@ Configuration hook 
1937    if ( !wxThePrintSetupData
->GetPrintPreviewCommand() ) 
1938       wxThePrintSetupData
->SetPrintPreviewCommand(PS_VIEWER_PROG
); 
1940    //   wxGetResource ("wxWindows", "PSView", &wxThePrintSetupData->m_previewCommand); 
1942    features 
= (wxThePrintSetupData
->GetPrintPreviewCommand() && 
1943                *wxThePrintSetupData
->GetPrintPreviewCommand()) ? 3 : 2; 
1945    wxRadioBox 
*radio1 
= new wxRadioBox(this, wxID_PRINTER_MODES
, _("PostScript:"), 
1947                                        wxSize(-1,-1), features
, 
1948                                        print_modes
, features
, wxRA_SPECIFY_ROWS
); 
1951    radio1
->Enable(0, FALSE
); 
1952    if (wxThePrintSetupData
->GetPrintPreviewCommand() && *wxThePrintSetupData
->GetPrintPreviewCommand()) 
1953       radio1
->Enable(2, FALSE
); 
1956    radio1
->SetSelection((int)wxThePrintSetupData
->GetPrinterMode()); 
1957    wxThePrintSetupData
->GetPrinterTranslation(&wx_printer_translate_x
, &wx_printer_translate_y
); 
1958    wxThePrintSetupData
->GetPrinterScaling(&wx_printer_scale_x
, &wx_printer_scale_y
); 
1960    sprintf (buf
, "%.2f", wx_printer_scale_x
); 
1963    (void) new wxStaticText(this, -1, _("X Scaling"), wxPoint(5, yPos
)); 
1964    /* wxTextCtrl *text1 = */ (void) new wxTextCtrl(this, wxID_PRINTER_X_SCALE
, buf
, wxPoint(100, yPos
), wxSize(100, -1)); 
1966    sprintf (buf
, "%.2f", wx_printer_scale_y
); 
1967    (void) new wxStaticText(this, -1, _("Y Scaling"), wxPoint(220, yPos
)); 
1968    /* wxTextCtrl *text2 = */ (void) new wxTextCtrl(this, wxID_PRINTER_Y_SCALE
, buf
, wxPoint(320, yPos
), wxSize(100, -1)); 
1972    (void) new wxStaticText(this, -1, _("X Translation"), wxPoint(5, yPos
)); 
1973    sprintf (buf
, "%.2ld", wx_printer_translate_x
); 
1974    /* wxTextCtrl *text3 = */ (void) new wxTextCtrl(this, wxID_PRINTER_X_TRANS
, buf
, wxPoint(100, yPos
), wxSize(100, -1)); 
1976    (void) new wxStaticText(this, -1, _("Y Translation"), wxPoint(220, yPos
)); 
1977    sprintf (buf
, "%.2ld", wx_printer_translate_y
); 
1978    /* wxTextCtrl *text4 = */ (void) new wxTextCtrl(this, wxID_PRINTER_Y_TRANS
, buf
, wxPoint(320, yPos
), wxSize(100, -1)); 
1982    delete[] orientation
; 
1983    delete[] print_modes
; 
1988 int wxPostScriptPrintDialog::ShowModal () 
1990   if ( wxDialog::ShowModal() == wxID_OK 
) 
1992 //    wxTextCtrl *text0 = (wxTextCtrl *)FindWindow(wxID_PRINTER_OPTIONS); 
1993       wxTextCtrl 
*text1 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_X_SCALE
); 
1994       wxTextCtrl 
*text2 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_Y_SCALE
); 
1995       wxTextCtrl 
*text3 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_X_TRANS
); 
1996       wxTextCtrl 
*text4 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_Y_TRANS
); 
1997 //    wxTextCtrl *text_prt = (wxTextCtrl *)FindWindow(wxID_PRINTER_COMMAND); 
1998       wxRadioBox 
*radio0 
= (wxRadioBox 
*)FindWindow(wxID_PRINTER_ORIENTATION
); 
1999       wxRadioBox 
*radio1 
= (wxRadioBox 
*)FindWindow(wxID_PRINTER_MODES
); 
2001       StringToDouble (WXSTRINGCAST text1
->GetValue (), &wxThePrintSetupData
->m_printerScaleX
); 
2002       StringToDouble (WXSTRINGCAST text2
->GetValue (), &wxThePrintSetupData
->m_printerScaleY
); 
2003       StringToLong (WXSTRINGCAST text3
->GetValue (), &wxThePrintSetupData
->m_printerTranslateX
); 
2004       StringToLong (WXSTRINGCAST text4
->GetValue (), &wxThePrintSetupData
->m_printerTranslateY
); 
2007       //      wxThePrintSetupData->SetPrinterOptions(WXSTRINGCAST text0->GetValue ()); 
2008       //      wxThePrintSetupData->SetPrinterCommand(WXSTRINGCAST text_prt->GetValue ()); 
2011       wxThePrintSetupData
->SetPrinterOrientation((radio0
->GetSelection() == 1 ? wxLANDSCAPE 
: wxPORTRAIT
)); 
2014       switch ( radio1
->GetSelection() ) { 
2015         case 0: wxThePrintSetupData
->SetPrinterMode(PS_PRINTER
); break; 
2016         case 1:  wxThePrintSetupData
->SetPrinterMode(PS_FILE
); break; 
2017         case 2: wxThePrintSetupData
->SetPrinterMode(PS_PREVIEW
); break; 
2026 // PostScript printer settings 
2027 // RETAINED FOR BACKWARD COMPATIBILITY 
2028 void wxSetPrinterCommand(const wxString
& cmd
) 
2030   wxThePrintSetupData
->SetPrinterCommand(cmd
); 
2033 void wxSetPrintPreviewCommand(const wxString
& cmd
) 
2035   wxThePrintSetupData
->SetPrintPreviewCommand(cmd
); 
2038 void wxSetPrinterOptions(const wxString
& flags
) 
2040   wxThePrintSetupData
->SetPrinterOptions(flags
); 
2043 void wxSetPrinterFile(const wxString
& f
) 
2045   wxThePrintSetupData
->SetPrinterFile(f
); 
2048 void wxSetPrinterOrientation(int orient
) 
2050   wxThePrintSetupData
->SetPrinterOrientation(orient
); 
2053 void wxSetPrinterScaling(double x
, double y
) 
2055   wxThePrintSetupData
->SetPrinterScaling(x
, y
); 
2058 void wxSetPrinterTranslation(long x
, long y
) 
2060   wxThePrintSetupData
->SetPrinterTranslation(x
, y
); 
2063 // 1 = Preview, 2 = print to file, 3 = send to printer 
2064 void wxSetPrinterMode(int mode
) 
2066   wxThePrintSetupData
->SetPrinterMode(mode
); 
2069 void wxSetAFMPath(const wxString
& f
) 
2071   wxThePrintSetupData
->SetAFMPath(f
); 
2074 // Get current values 
2075 wxString 
wxGetPrinterCommand() 
2077   return wxThePrintSetupData
->GetPrinterCommand(); 
2080 wxString 
wxGetPrintPreviewCommand() 
2082   return wxThePrintSetupData
->GetPrintPreviewCommand(); 
2085 wxString 
wxGetPrinterOptions() 
2087   return wxThePrintSetupData
->GetPrinterOptions(); 
2090 wxString 
wxGetPrinterFile() 
2092   return wxThePrintSetupData
->GetPrinterFile(); 
2095 int wxGetPrinterOrientation() 
2097   return wxThePrintSetupData
->GetPrinterOrientation(); 
2100 void wxGetPrinterScaling(double* x
, double* y
) 
2102   wxThePrintSetupData
->GetPrinterScaling(x
, y
); 
2105 void wxGetPrinterTranslation(long *x
, long *y
) 
2107   wxThePrintSetupData
->GetPrinterTranslation(x
, y
); 
2110 int wxGetPrinterMode() 
2112   return wxThePrintSetupData
->GetPrinterMode(); 
2115 wxString 
wxGetAFMPath() 
2117   return wxThePrintSetupData
->GetAFMPath(); 
2124 wxPrintSetupData::wxPrintSetupData() 
2126   m_printerOrient 
= wxPORTRAIT
; 
2127   m_printerScaleX 
= (double)1.0; 
2128   m_printerScaleY 
= (double)1.0; 
2129   m_printerTranslateX 
= 0; 
2130   m_printerTranslateY 
= 0; 
2131   m_printerMode 
= wxPRINT_MODE_FILE
; 
2132   m_printColour 
= TRUE
; 
2135 wxPrintSetupData::~wxPrintSetupData() 
2139 void wxPrintSetupData::operator=(wxPrintSetupData
& data
) 
2141   SetPrinterCommand(data
.GetPrinterCommand()); 
2142   SetPrintPreviewCommand(data
.GetPrintPreviewCommand()); 
2143   SetPrinterOptions(data
.GetPrinterOptions()); 
2145   data
.GetPrinterTranslation(&x
, &y
); 
2146   SetPrinterTranslation(x
, y
); 
2149   data
.GetPrinterScaling(&x1
, &y1
); 
2150   SetPrinterScaling(x1
, y1
); 
2152   SetPrinterOrientation(data
.GetPrinterOrientation()); 
2153   SetPrinterMode(data
.GetPrinterMode()); 
2154   SetAFMPath(data
.GetAFMPath()); 
2155   SetPaperName(data
.GetPaperName()); 
2156   SetColour(data
.GetColour()); 
2159 // Initialize from a wxPrintData object (wxPrintData should now be used instead of wxPrintSetupData). 
2160 void wxPrintSetupData::operator=(const wxPrintData
& data
) 
2162     SetPrinterCommand(data
.GetPrinterCommand()); 
2163     SetPrintPreviewCommand(data
.GetPreviewCommand()); 
2164     SetPrinterOptions(data
.GetPrinterOptions()); 
2165     SetPrinterTranslation(data
.GetPrinterTranslateX(), data
.GetPrinterTranslateY()); 
2166     SetPrinterScaling(data
.GetPrinterScaleX(), data
.GetPrinterScaleY()); 
2167     SetPrinterOrientation(data
.GetOrientation()); 
2168     SetPrinterMode((int) data
.GetPrintMode()); 
2169     SetAFMPath(data
.GetFontMetricPath()); 
2170     SetPaperName(wxThePrintPaperDatabase
->ConvertIdToName(data
.GetPaperId())); 
2171     SetColour(data
.GetColour()); 
2172     SetPrinterFile(data
.GetFilename()); 
2175 void wxInitializePrintSetupData(bool init
) 
2179     wxThePrintSetupData 
= new wxPrintSetupData
; 
2181     wxThePrintSetupData
->SetPrintPreviewCommand(PS_VIEWER_PROG
); 
2182     wxThePrintSetupData
->SetPrinterOrientation(wxPORTRAIT
); 
2183     wxThePrintSetupData
->SetPrinterMode(wxPRINT_MODE_PREVIEW
); 
2184     wxThePrintSetupData
->SetPaperName(_("A4 sheet, 210 x 297 mm")); 
2186     // Could have a .ini file to read in some defaults 
2187     // - and/or use environment variables, e.g. WXWIN 
2189     wxThePrintSetupData
->SetPrinterCommand("print"); 
2190     wxThePrintSetupData
->SetPrinterOptions("/nonotify/queue=psqueue"); 
2191     wxThePrintSetupData
->SetAFMPath("sys$ps_font_metrics:"); 
2194     wxThePrintSetupData
->SetPrinterCommand("print"); 
2195     wxThePrintSetupData
->SetAFMPath("c:\\windows\\system\\"); 
2196     wxThePrintSetupData
->SetPrinterOptions(""); 
2198 #if !defined(__VMS__) && !defined(__WXMSW__) 
2199     wxThePrintSetupData
->SetPrinterCommand("lpr"); 
2200     wxThePrintSetupData
->SetPrinterOptions(""); 
2201     wxThePrintSetupData
->SetAFMPath(""); 
2206     if (wxThePrintSetupData
) 
2207       delete wxThePrintSetupData
; 
2208      wxThePrintSetupData 
= (wxPrintSetupData 
*) NULL
; 
2212 // A module to allow initialization/cleanup of PostScript-related 
2213 // things without calling these functions from app.cpp. 
2215 class WXDLLEXPORT wxPostScriptModule
: public wxModule
 
2217 DECLARE_DYNAMIC_CLASS(wxPostScriptModule
) 
2219     wxPostScriptModule() {} 
2224 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptModule
, wxModule
) 
2227  * Initialization/cleanup module 
2230 bool wxPostScriptModule::OnInit() 
2232     wxInitializePrintSetupData(); 
2237 void wxPostScriptModule::OnExit() 
2239     wxInitializePrintSetupData(FALSE
);