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" 
  28 #if wxUSE_PRINTING_ARCHITECTURE 
  32 #include "wx/window.h" 
  33 #include "wx/dcmemory.h" 
  36 #include "wx/filedlg.h" 
  38 #include "wx/msgdlg.h" 
  41 #include "wx/generic/dcpsg.h" 
  42 #include "wx/generic/prntdlgg.h" 
  43 #include "wx/button.h" 
  44 #include "wx/stattext.h" 
  45 #include "wx/radiobox.h" 
  46 #include "wx/textctrl.h" 
  47 #include "wx/prntbase.h" 
  72 //----------------------------------------------------------------------------- 
  73 // start and end of document/page 
  74 //----------------------------------------------------------------------------- 
  76 static const char *wxPostScriptHeaderEllipse 
= "\ 
  77 /ellipsedict 8 dict def\n\ 
  78 ellipsedict /mtrx matrix put\n\ 
  82     /startangle exch def\n\ 
  87     /savematrix mtrx currentmatrix def\n\ 
  90     0 0 1 startangle endangle arc\n\ 
  91     savematrix setmatrix\n\ 
  96 static const char *wxPostScriptHeaderEllipticArc
= "\ 
  97 /ellipticarcdict 8 dict def\n\ 
  98 ellipticarcdict /mtrx matrix put\n\ 
 100 { ellipticarcdict begin\n\ 
 102   /endangle exch def\n\ 
 103   /startangle exch def\n\ 
 108   /savematrix mtrx currentmatrix def\n\ 
 111   do_fill { 0 0 moveto } if\n\ 
 112   0 0 1 startangle endangle arc\n\ 
 113   savematrix setmatrix\n\ 
 114   do_fill { fill }{ stroke } ifelse\n\ 
 118 static const char *wxPostScriptHeaderSpline 
= "\ 
 119 /DrawSplineSection {\n\ 
 126     /xa x1 x2 x1 sub 0.666667 mul add def\n\ 
 127     /ya y1 y2 y1 sub 0.666667 mul add def\n\ 
 128     /xb x3 x2 x3 sub 0.666667 mul add def\n\ 
 129     /yb y3 y2 y3 sub 0.666667 mul add def\n\ 
 131     xa ya xb yb x3 y3 curveto\n\ 
 135 static const char *wxPostScriptHeaderColourImage 
= "\ 
 136 %% define 'colorimage' if it isn't defined\n\ 
 137 %%   ('colortogray' and 'mergeprocs' come from xwd2ps\n\ 
 139 /colorimage where   %% do we know about 'colorimage'?\n\ 
 140   { pop }           %% yes: pop off the 'dict' returned\n\ 
 141   {                 %% no:  define one\n\ 
 142     /colortogray {  %% define an RGB->I function\n\ 
 143       /rgbdata exch store    %% call input 'rgbdata'\n\ 
 144       rgbdata length 3 idiv\n\ 
 145       /npixls exch store\n\ 
 147       0 1 npixls 1 sub {\n\ 
 149         rgbdata rgbindx       get 20 mul    %% Red\n\ 
 150         rgbdata rgbindx 1 add get 32 mul    %% Green\n\ 
 151         rgbdata rgbindx 2 add get 12 mul    %% Blue\n\ 
 152         add add 64 idiv      %% I = .5G + .31R + .18B\n\ 
 154         /rgbindx rgbindx 3 add store\n\ 
 156       grays 0 npixls getinterval\n\ 
 159     %% Utility procedure for colorimage operator.\n\ 
 160     %% This procedure takes two procedures off the\n\ 
 161     %% stack and merges them into a single procedure.\n\ 
 163     /mergeprocs { %% def\n\ 
 182     /colorimage { %% def\n\ 
 183       pop pop     %% remove 'false 3' operands\n\ 
 184       {colortogray} mergeprocs\n\ 
 187   } ifelse          %% end of 'false' case\n\ 
 190 static char wxPostScriptHeaderReencodeISO1
[] = 
 192 "dup dup findfont dup length dict begin\n" 
 193 "{ 1 index /FID ne { def }{ pop pop } ifelse } forall\n" 
 194 "/Encoding ISOLatin1Encoding def\n" 
 195 "currentdict end definefont\n" 
 197 "/ISOLatin1Encoding [\n" 
 198 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 199 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 200 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 201 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 202 "/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright\n" 
 203 "/parenleft/parenright/asterisk/plus/comma/minus/period/slash\n" 
 204 "/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon\n" 
 205 "/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N\n" 
 206 "/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright\n" 
 207 "/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m\n" 
 208 "/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde\n" 
 209 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 210 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 211 "/.notdef/dotlessi/grave/acute/circumflex/tilde/macron/breve\n" 
 212 "/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut\n"; 
 214 static char wxPostScriptHeaderReencodeISO2
[] = 
 215 "/ogonek/caron/space/exclamdown/cent/sterling/currency/yen/brokenbar\n" 
 216 "/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot\n" 
 217 "/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior\n" 
 218 "/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine\n" 
 219 "/guillemotright/onequarter/onehalf/threequarters/questiondown\n" 
 220 "/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla\n" 
 221 "/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex\n" 
 222 "/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis\n" 
 223 "/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute\n" 
 224 "/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis\n" 
 225 "/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave\n" 
 226 "/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex\n" 
 227 "/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis\n" 
 228 "/yacute/thorn/ydieresis\n" 
 231 //------------------------------------------------------------------------------- 
 233 //------------------------------------------------------------------------------- 
 235 wxPostScriptDC::wxPostScriptDC () 
 237     m_pstream 
= (FILE*) NULL
; 
 247     m_underlinePosition 
= 0.0; 
 248     m_underlineThickness 
= 0.0; 
 250     m_signX 
=  1;  // default x-axis left to right 
 251     m_signY 
= -1;  // default y-axis bottom up -> top down 
 253     // Compatibility only 
 254     // HH: Doesn't seem to work for wxMSW... 
 256     m_printData 
= * wxThePrintSetupData
; 
 260 wxPostScriptDC::wxPostScriptDC (const wxString
& file
, bool interactive
, wxWindow 
*parent
) 
 262     m_pstream 
= (FILE*) NULL
; 
 272     m_underlinePosition 
= 0.0; 
 273     m_underlineThickness 
= 0.0; 
 275     m_signX 
=  1;  // default x-axis left to right 
 276     m_signY 
= -1;  // default y-axis bottom up -> top down 
 278     Create(file
, interactive
, parent
); 
 281 bool wxPostScriptDC::Create(const wxString
& file
, bool interactive
, wxWindow 
*parent
) 
 283     m_isInteractive 
= interactive
; 
 286     m_printData
.SetFilename(file
); 
 289     // Can only send to file in Windows 
 290     m_printData
.SetPrintMode(wxPRINT_MODE_FILE
); 
 295         if ((m_ok 
= PrinterDialog (parent
) ) == FALSE
) return FALSE
; 
 305 wxPostScriptDC::wxPostScriptDC (const wxPrintData
& printData
) 
 307     m_pstream 
= (FILE*) NULL
; 
 317     m_underlinePosition 
= 0.0; 
 318     m_underlineThickness 
= 0.0; 
 320     m_signX 
=  1;  // default x-axis left to right 
 321     m_signY 
= -1;  // default y-axis bottom up -> top down 
 323     m_printData 
= printData
; 
 328 wxPostScriptDC::~wxPostScriptDC () 
 333         m_pstream 
= (FILE*) NULL
; 
 337 bool wxPostScriptDC::Ok() const 
 342 // This dialog is deprecated now: use wxGenericPrintDialog or the printing framework 
 343 bool wxPostScriptDC::PrinterDialog(wxWindow 
*parent
) 
 345     wxPostScriptPrintDialog 
dialog( parent
, _("Printer Settings"), wxPoint(150, 150), wxSize(400, 400), 
 346                                     wxDEFAULT_DIALOG_STYLE 
| wxDIALOG_MODAL 
); 
 347     m_ok 
= (dialog
.ShowModal () == wxID_OK
); 
 349     if (!m_ok
) return FALSE
; 
 351     if ((m_printData
.GetFilename() == "") && 
 352         (m_printData
.GetPrintMode() == wxPRINT_MODE_PREVIEW  
|| 
 353          m_printData
.GetPrintMode() == wxPRINT_MODE_PRINTER
)) 
 357       m_printData
.SetFilename("preview"); 
 359       // For PS_PRINTER action this depends on a Unix-style print spooler 
 360       // since the wx_printer_file can be destroyed during a session 
 361       // @@@ TODO: a Windows-style answer for non-Unix 
 363       wxGetUserId (userId
, sizeof (userId
) / sizeof (char)); 
 365       wxStrcpy (tmp
, wxT("/tmp/preview_")); 
 366       wxStrcat (tmp
, userId
); 
 367       m_printData
.SetFilename(tmp
); 
 370       wxStrcpy(tmp2
, m_printData
.GetFilename()); 
 371       wxStrcat (tmp2
, wxT(".ps")); 
 372       m_printData
.SetFilename(tmp2
); 
 374     else if ((m_printData
.GetFilename() == wxT("")) && (m_printData
.GetPrintMode() == wxPRINT_MODE_FILE
)) 
 376       wxString file 
= wxSaveFileSelector (_("PostScript"), wxT("ps")); 
 377       if ( file
.IsEmpty() ) 
 383       m_printData
.SetFilename(file
); 
 390 void wxPostScriptDC::SetClippingRegion (long x
, long y
, long w
, long h
) 
 392     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 394     if (m_clipping
) return; 
 396     wxDC::SetClippingRegion( x
, y
, w
, h 
); 
 405             "closepath clip newpath\n", 
 406             XLOG2DEV(x
),   YLOG2DEV(y
),  
 407             XLOG2DEV(x
+w
), YLOG2DEV(y
),  
 408             XLOG2DEV(x
+w
), YLOG2DEV(y
+h
), 
 409             XLOG2DEV(x
),   YLOG2DEV(y
+h
) ); 
 412 void wxPostScriptDC::SetClippingRegion( const wxRegion 
&WXUNUSED(region
) ) 
 414     wxFAIL_MSG( wxT("wxPostScriptDC::SetClippingRegion not implemented.") ); 
 417 void wxPostScriptDC::DestroyClippingRegion() 
 419     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 421     wxDC::DestroyClippingRegion(); 
 426         fprintf( m_pstream
, "grestore\n" ); 
 430 void wxPostScriptDC::Clear() 
 432     wxFAIL_MSG( wxT("wxPostScriptDC::Clear not implemented.") ); 
 435 void wxPostScriptDC::DoFloodFill (long WXUNUSED(x
), long WXUNUSED(y
), const wxColour 
&WXUNUSED(col
), int WXUNUSED(style
)) 
 437     wxFAIL_MSG( wxT("wxPostScriptDC::FloodFill not implemented.") ); 
 440 bool wxPostScriptDC::DoGetPixel (long WXUNUSED(x
), long WXUNUSED(y
), wxColour 
* WXUNUSED(col
)) const 
 442     wxFAIL_MSG( wxT("wxPostScriptDC::GetPixel not implemented.") ); 
 446 void wxPostScriptDC::DoCrossHair (long WXUNUSED(x
), long WXUNUSED(y
)) 
 448     wxFAIL_MSG( wxT("wxPostScriptDC::CrossHair not implemented.") ); 
 451 void wxPostScriptDC::DoDrawLine (long x1
, long y1
, long x2
, long y2
) 
 453     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 455     if  (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 464             XLOG2DEV(x1
), YLOG2DEV(y1
), 
 465             XLOG2DEV(x2
), YLOG2DEV (y2
) ); 
 467     CalcBoundingBox( x1
, y1 
); 
 468     CalcBoundingBox( x2
, y2 
); 
 471 #define RAD2DEG 57.29577951308 
 473 void wxPostScriptDC::DoDrawArc (long x1
, long y1
, long x2
, long y2
, long xc
, long yc
) 
 475     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 479     long radius 
= (long) sqrt(dx
*dx
+dy
*dy
); 
 480     double alpha1
, alpha2
; 
 482     if (x1 
== x2 
&& y1 
== y2
) 
 487     else if (radius 
== 0.0) 
 489         alpha1 
= alpha2 
= 0.0; 
 493         alpha1 
= (x1 
- xc 
== 0) ? 
 494             (y1 
- yc 
< 0) ? 90.0 : -90.0 : 
 495                 -atan2(double(y1
-yc
), double(x1
-xc
)) * RAD2DEG
; 
 496         alpha2 
= (x2 
- xc 
== 0) ? 
 497             (y2 
- yc 
< 0) ? 90.0 : -90.0 : 
 498                 -atan2(double(y2
-yc
), double(x2
-xc
)) * RAD2DEG
; 
 500     while (alpha1 
<= 0)   alpha1 
+= 360; 
 501     while (alpha2 
<= 0)   alpha2 
+= 360; // adjust angles to be between 
 502     while (alpha1 
> 360)  alpha1 
-= 360; // 0 and 360 degree 
 503     while (alpha2 
> 360)  alpha2 
-= 360; 
 505     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 511                 "%ld %ld %ld %ld %ld %ld ellipse\n" 
 515                 XLOG2DEV(xc
), YLOG2DEV(yc
), XLOG2DEVREL(radius
), YLOG2DEVREL(radius
), (long)alpha1
, (long) alpha2
, 
 516                 XLOG2DEV(xc
), YLOG2DEV(yc
) ); 
 518         CalcBoundingBox( xc
-radius
, yc
-radius 
); 
 519         CalcBoundingBox( xc
+radius
, yc
+radius 
); 
 522     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 528                 "%ld %ld %ld %ld %ld %ld ellipse\n" 
 532                 XLOG2DEV(xc
), YLOG2DEV(yc
), XLOG2DEVREL(radius
), YLOG2DEVREL(radius
), (long)alpha1
, (long) alpha2
, 
 533                 XLOG2DEV(xc
), YLOG2DEV(yc
) ); 
 535         CalcBoundingBox( xc
-radius
, yc
-radius 
); 
 536         CalcBoundingBox( xc
+radius
, yc
+radius 
); 
 540 void wxPostScriptDC::DoDrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
) 
 542     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 544     if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360; 
 545     if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360; 
 551         DrawEllipse(x
,y
,w
,h
); 
 555     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 561                 "%ld %ld %ld %ld %ld %ld true ellipticarc\n", 
 562                 XLOG2DEV(x
+w
/2), YLOG2DEV(y
+h
/2), XLOG2DEVREL(w
/2), YLOG2DEVREL(h
/2), (long)sa
, (long)ea 
); 
 564         CalcBoundingBox( x 
,y 
); 
 565         CalcBoundingBox( x
+w
, y
+h 
); 
 568     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 574                 "%ld %ld %ld %ld %ld %ld false ellipticarc\n", 
 575                 XLOG2DEV(x
+w
/2), YLOG2DEV(y
+h
/2), XLOG2DEVREL(w
/2), YLOG2DEVREL(h
/2), (long)sa
, (long)ea 
); 
 577         CalcBoundingBox( x 
,y 
); 
 578         CalcBoundingBox( x
+w
, y
+h 
); 
 582 void wxPostScriptDC::DoDrawPoint (long x
, long y
) 
 584     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 586     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 595             XLOG2DEV(x
),   YLOG2DEV(y
), 
 596             XLOG2DEV(x
+1), YLOG2DEV(y
) ); 
 598     CalcBoundingBox( x
, y 
); 
 601 void wxPostScriptDC::DoDrawPolygon (int n
, wxPoint points
[], long xoffset
, long yoffset
, int WXUNUSED(fillStyle
)) 
 603     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 607     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 611         fprintf( m_pstream
, "newpath\n" ); 
 613         long xx 
= XLOG2DEV(points
[0].x 
+ xoffset
); 
 614         long yy 
= YLOG2DEV(points
[0].y 
+ yoffset
); 
 616         fprintf( m_pstream
, "%ld %ld moveto\n", xx
, yy 
); 
 618         CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 620         for (int i 
= 1; i 
< n
; i
++) 
 622             xx 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 623             yy 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 625             fprintf( m_pstream
, "%ld %ld lineto\n", xx
, yy 
); 
 627             CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 630         fprintf( m_pstream
, "fill\n" ); 
 633     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 637         fprintf( m_pstream
, "newpath\n" ); 
 639         long xx 
= XLOG2DEV(points
[0].x 
+ xoffset
); 
 640         long yy 
= YLOG2DEV(points
[0].y 
+ yoffset
); 
 642         fprintf( m_pstream
, "%ld %ld moveto\n", xx
, yy 
); 
 644         CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 646         for (int i 
= 1; i 
< n
; i
++) 
 648             xx 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 649             yy 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 651             fprintf( m_pstream
, "%ld %ld lineto\n", xx
, yy 
); 
 653             CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 656         fprintf( m_pstream
, "fill\n" ); 
 660 void wxPostScriptDC::DoDrawLines (int n
, wxPoint points
[], long xoffset
, long yoffset
) 
 662     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 664     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 671     for ( i 
=0; i
<n 
; i
++ ) 
 673         CalcBoundingBox( XLOG2DEV(points
[i
].x
+xoffset
), YLOG2DEV(points
[i
].y
+yoffset
)); 
 679             XLOG2DEV(points
[0].x
+xoffset
), YLOG2DEV(points
[0].y
+yoffset
) ); 
 681     for (i 
= 1; i 
< n
; i
++) 
 685                 XLOG2DEV(points
[i
].x
+xoffset
), YLOG2DEV(points
[i
].y
+yoffset
) ); 
 688     fprintf( m_pstream
, "stroke\n" ); 
 691 void wxPostScriptDC::DoDrawRectangle (long x
, long y
, long width
, long height
) 
 693     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 695     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 707                 XLOG2DEV(x
),         YLOG2DEV(y
), 
 708                 XLOG2DEV(x 
+ width
), YLOG2DEV(y
), 
 709                 XLOG2DEV(x 
+ width
), YLOG2DEV(y 
+ height
), 
 710                 XLOG2DEV(x
),         YLOG2DEV(y 
+ height
) ); 
 712         CalcBoundingBox( x
, y 
); 
 713         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 716     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 728                 XLOG2DEV(x
),         YLOG2DEV(y
), 
 729                 XLOG2DEV(x 
+ width
), YLOG2DEV(y
), 
 730                 XLOG2DEV(x 
+ width
), YLOG2DEV(y 
+ height
), 
 731                 XLOG2DEV(x
),         YLOG2DEV(y 
+ height
) ); 
 733         CalcBoundingBox( x
, y 
); 
 734         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 738 void wxPostScriptDC::DoDrawRoundedRectangle (long x
, long y
, long width
, long height
, double radius
) 
 740     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 744         // Now, a negative radius is interpreted to mean 
 745         // 'the proportion of the smallest X or Y dimension' 
 746         double smallest 
= 0.0; 
 751         radius 
=  (-radius 
* smallest
); 
 754     long rad 
= (long) radius
; 
 756     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 760         /* Draw rectangle anticlockwise */ 
 763                 "%ld %ld %ld 90 180 arc\n" 
 765                 "%ld %ld %ld 180 270 arc\n" 
 767                 "%ld %ld %ld 270 0 arc\n" 
 769                 "%ld %ld %ld 0 90 arc\n" 
 773                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y 
+ rad
), XLOG2DEVREL(rad
), 
 774                 XLOG2DEV(x
), YLOG2DEV(y 
+ rad
), 
 775                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y 
+ height 
- rad
), XLOG2DEVREL(rad
), 
 776                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ height
), 
 777                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ height 
- rad
), XLOG2DEVREL(rad
), 
 778                 XLOG2DEV(x 
+ width
), YLOG2DEV(y 
+ rad
), 
 779                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ rad
), XLOG2DEVREL(rad
), 
 780                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y
) ); 
 782         CalcBoundingBox( x
, y 
); 
 783         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 786     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 790         /* Draw rectangle anticlockwise */ 
 793                 "%ld %ld %ld 90 180 arc\n" 
 795                 "%ld %ld %ld 180 270 arc\n" 
 797                 "%ld %ld %ld 270 0 arc\n" 
 799                 "%ld %ld %ld 0 90 arc\n" 
 803                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y 
+ rad
), XLOG2DEVREL(rad
), 
 804                 XLOG2DEV(x
), YLOG2DEV(y 
+ rad
), 
 805                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y 
+ height 
- rad
), XLOG2DEVREL(rad
), 
 806                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ height
), 
 807                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ height 
- rad
), XLOG2DEVREL(rad
), 
 808                 XLOG2DEV(x 
+ width
), YLOG2DEV(y 
+ rad
), 
 809                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ rad
), XLOG2DEVREL(rad
), 
 810                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y
) ); 
 812         CalcBoundingBox( x
, y 
); 
 813         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 817 void wxPostScriptDC::DoDrawEllipse (long x
, long y
, long width
, long height
) 
 819     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 821     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 827                 "%ld %ld %ld %ld 0 360 ellipse\n" 
 829                 XLOG2DEV(x 
+ width 
/ 2), YLOG2DEV(y 
+ height 
/ 2),  
 830                 XLOG2DEV(width 
/ 2), YLOG2DEVREL(height 
/ 2) ); 
 832         CalcBoundingBox( x 
- width
, y 
- height 
); 
 833         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 836     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 842                 "%ld %ld %ld %ld 0 360 ellipse\n" 
 844                 XLOG2DEV(x 
+ width 
/ 2), YLOG2DEV(y 
+ height 
/ 2),  
 845                 XLOG2DEV(width 
/ 2), YLOG2DEVREL(height 
/ 2) ); 
 847         CalcBoundingBox( x 
- width
, y 
- height 
); 
 848         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 852 void wxPostScriptDC::DoDrawIcon( const wxIcon
& icon
, long x
, long y 
) 
 854     DrawBitmap( icon
, x
, y
, TRUE 
); 
 857 /* this has to be char, not wxChar */ 
 858 static char hexArray
[] = "0123456789ABCDEF"; 
 859 static void LocalDecToHex( int dec
, char *buf 
) 
 861     int firstDigit 
= (int)(dec
/16.0); 
 862     int secondDigit 
= (int)(dec 
- (firstDigit
*16.0)); 
 863     buf
[0] = hexArray
[firstDigit
]; 
 864     buf
[1] = hexArray
[secondDigit
]; 
 868 void wxPostScriptDC::DoDrawBitmap( const wxBitmap
& bitmap
, long x
, long y
, bool WXUNUSED(useMask
) ) 
 870     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 872     if (!bitmap
.Ok()) return; 
 874     wxImage 
image( bitmap 
); 
 876     if (!image
.Ok()) return; 
 878     long ww 
= XLOG2DEVREL(image
.GetWidth()); 
 879     long hh 
= YLOG2DEVREL(image
.GetHeight()); 
 881     image 
= image
.Scale( ww
, hh 
); 
 883     if (!image
.Ok()) return; 
 885     long xx 
= XLOG2DEV(x
); 
 886     long yy 
= YLOG2DEV(y 
+ bitmap
.GetHeight()); 
 889             "/origstate save def\n" 
 891             "/pix %ld string def\n" 
 892             "/grays %ld string def\n" 
 895             "%ld %ld translate\n" 
 898             "[%ld 0 0 %ld 0 %ld]\n" 
 899             "{currentfile pix readhexstring pop}\n" 
 900             "false 3 colorimage\n", 
 901             ww
, ww
, xx
, yy
, ww
, hh
, ww
, hh
, ww
, -hh
, hh 
); 
 903     for (int j 
= 0; j 
< hh
; j
++) 
 905         for (int i 
= 0; i 
< ww
; i
++) 
 908             LocalDecToHex( image
.GetRed(i
,j
), buffer 
); 
 909             fprintf( m_pstream
, buffer 
); 
 910             LocalDecToHex( image
.GetGreen(i
,j
), buffer 
); 
 911             fprintf( m_pstream
, buffer 
); 
 912             LocalDecToHex( image
.GetBlue(i
,j
), buffer 
); 
 913             fprintf( m_pstream
, buffer 
); 
 915         fprintf( m_pstream
, "\n" ); 
 918     fprintf( m_pstream
, "end\n" ); 
 919     fprintf( m_pstream
, "origstate restore\n" ); 
 922 void wxPostScriptDC::SetFont( const wxFont
& font 
) 
 924     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 926     if (!font
.Ok())  return; 
 931     const char *style 
= ""; 
 932     int Style 
= m_font
.GetStyle(); 
 933     int Weight 
= m_font
.GetWeight(); 
 935     switch (m_font
.GetFamily()) 
 945 //          name = "/Times-Roman"; 
 946             name 
= "/Times"; // Altered by EDZ 
 949             name 
= "/Zapf-Chancery-MediumItalic"; 
 954         case wxDEFAULT
: // Sans Serif Font 
 955             name 
= "/LucidaSans"; 
 958     if (Style 
== wxNORMAL 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 960         if (m_font
.GetFamily () == wxROMAN
) 
 965     else if (Style 
== wxNORMAL 
&& Weight 
== wxBOLD
) 
 969     else if (Style 
== wxITALIC 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 971         if (m_font
.GetFamily () == wxROMAN
) 
 976     else if (Style 
== wxITALIC 
&& Weight 
== wxBOLD
) 
 978         if (m_font
.GetFamily () == wxROMAN
) 
 979             style 
= "-BoldItalic"; 
 981             style 
= "-BoldOblique"; 
 983     else if (Style 
== wxSLANT 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 985         if (m_font
.GetFamily () == wxROMAN
) 
 990     else if (Style 
== wxSLANT 
&& Weight 
== wxBOLD
) 
 992         if (m_font
.GetFamily () == wxROMAN
) 
 993             style 
= "-BoldItalic"; 
 995             style 
= "-BoldOblique"; 
1003     strcpy( buffer
, name 
); 
1004     strcat( buffer
, style 
); 
1006     fprintf( m_pstream
, buffer 
); 
1007     fprintf( m_pstream
, " reencodeISO def\n" ); 
1008     fprintf( m_pstream
, buffer 
); 
1009     fprintf( m_pstream
, " findfont\n" ); 
1011     fprintf( m_pstream
, "%d scalefont setfont\n", YLOG2DEVREL(m_font
.GetPointSize()) ); 
1013     fprintf( m_pstream
, "%ld scalefont setfont\n", YLOG2DEVREL(m_font
.GetPointSize()) ); 
1017 void wxPostScriptDC::SetPen( const wxPen
& pen 
) 
1019     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1021     if (!pen
.Ok()) return; 
1023     int oldStyle 
= m_pen
.GetStyle(); 
1028     fprintf( m_pstream
, "%d setlinewidth\n", XLOG2DEVREL(m_pen
.GetWidth()) ); 
1030     fprintf( m_pstream
, "%ld setlinewidth\n", XLOG2DEVREL(m_pen
.GetWidth()) ); 
1033      Line style - WRONG: 2nd arg is OFFSET 
1035      Here, I'm afraid you do not conceive meaning of parameters of 'setdash' 
1036      operator correctly. You should look-up this in the Red Book: the 2nd parame- 
1037      ter is not number of values in the array of the first one, but an offset 
1038      into this description of the pattern. I mean a real *offset* not index 
1039      into array. I.e. If the command is [3 4] 1 setdash   is used, then there 
1040      will be first black line *2* units long, then space 4 units, then the 
1041      pattern of *3* units black, 4 units space will be repeated. 
1044     static const char *dotted 
= "[2 5] 2"; 
1045     static const char *short_dashed 
= "[4 4] 2"; 
1046     static const char *long_dashed 
= "[4 8] 2"; 
1047     static const char *dotted_dashed 
= "[6 6 2 6] 4"; 
1049     const char *psdash 
= (char *) NULL
; 
1050     switch (m_pen
.GetStyle()) 
1052         case wxDOT
:           psdash 
= dotted
;         break; 
1053         case wxSHORT_DASH
:    psdash 
= short_dashed
;   break; 
1054         case wxLONG_DASH
:     psdash 
= long_dashed
;    break; 
1055         case wxDOT_DASH
:      psdash 
= dotted_dashed
;  break; 
1058         default:              psdash 
= "[] 0";         break; 
1061     if (oldStyle 
!= m_pen
.GetStyle()) 
1063         fprintf( m_pstream
, psdash 
); 
1064         fprintf( m_pstream
," setdash\n" ); 
1068     unsigned char red 
= m_pen
.GetColour().Red(); 
1069     unsigned char blue 
= m_pen
.GetColour().Blue(); 
1070     unsigned char green 
= m_pen
.GetColour().Green(); 
1074         // Anything not white is black 
1075         if (! (red 
== (unsigned char) 255 &&  
1076                blue 
== (unsigned char) 255 && 
1077                green 
== (unsigned char) 255) ) 
1079             red 
= (unsigned char) 0; 
1080             green 
= (unsigned char) 0; 
1081             blue 
= (unsigned char) 0; 
1086     if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1088         double redPS 
= (double)(red
) / 255.0; 
1089         double bluePS 
= (double)(blue
) / 255.0; 
1090         double greenPS 
= (double)(green
) / 255.0; 
1093                 "%.8f %.8f %.8f setrgbcolor\n", 
1094                 redPS
, greenPS
, bluePS 
); 
1097         m_currentBlue 
= blue
; 
1098         m_currentGreen 
= green
; 
1102 void wxPostScriptDC::SetBrush( const wxBrush
& brush 
) 
1104     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1106     if (!brush
.Ok()) return; 
1111     unsigned char red 
= m_brush
.GetColour().Red(); 
1112     unsigned char blue 
= m_brush
.GetColour().Blue(); 
1113     unsigned char green 
= m_brush
.GetColour().Green(); 
1117         // Anything not white is black 
1118         if (! (red 
== (unsigned char) 255 &&  
1119                blue 
== (unsigned char) 255 && 
1120                green 
== (unsigned char) 255) ) 
1122             red 
= (unsigned char) 0; 
1123             green 
= (unsigned char) 0; 
1124             blue 
= (unsigned char) 0; 
1129     if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1131         double redPS 
= (double)(red
) / 255.0; 
1132         double bluePS 
= (double)(blue
) / 255.0; 
1133         double greenPS 
= (double)(green
) / 255.0; 
1136                 "%.8f %.8f %.8f setrgbcolor\n", 
1137                 redPS
, greenPS
, bluePS 
); 
1140         m_currentBlue 
= blue
; 
1141         m_currentGreen 
= green
; 
1145 void wxPostScriptDC::DoDrawText( const wxString
& text
, long x
, long y 
) 
1147     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1151     if (m_textForegroundColour
.Ok()) 
1153         unsigned char red 
= m_textForegroundColour
.Red(); 
1154         unsigned char blue 
= m_textForegroundColour
.Blue(); 
1155         unsigned char green 
= m_textForegroundColour
.Green(); 
1159             // Anything not white is black 
1160             if (! (red 
== (unsigned char) 255 &&  
1161                    blue 
== (unsigned char) 255 && 
1162                    green 
== (unsigned char) 255)) 
1164                 red 
= (unsigned char) 0; 
1165                 green 
= (unsigned char) 0; 
1166                 blue 
= (unsigned char) 0; 
1170         // maybe setgray here ? 
1171         if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1173             double redPS 
= (double)(red
) / 255.0; 
1174             double bluePS 
= (double)(blue
) / 255.0; 
1175             double greenPS 
= (double)(green
) / 255.0; 
1178                     "%.8f %.8f %.8f setrgbcolor\n", 
1179                     redPS
, greenPS
, bluePS 
); 
1182             m_currentBlue 
= blue
; 
1183             m_currentGreen 
= green
; 
1187     int size 
= m_font
.GetPointSize(); 
1189     long by 
= y 
+ (long)floor( double(size
) * 2.0 / 3.0 ); // approximate baseline 
1190     fprintf( m_pstream
, "%ld %ld moveto\n", XLOG2DEV(x
), YLOG2DEV(by
) ); 
1192     /* I don't know how to write char to a stream, so I use a mini string */ 
1196     fprintf( m_pstream
, "(" ); 
1197     const wxWX2MBbuf textbuf 
= text
.mb_str(); 
1198     int len 
= strlen(textbuf
); 
1200     for (i 
= 0; i 
< len
; i
++) 
1202         int c 
= (unsigned char) textbuf
[i
]; 
1203         if (c 
== ')' || c 
== '(' || c 
== '\\') 
1205             /* Cope with special characters */ 
1206             fprintf( m_pstream
, "\\" ); 
1207             tmpbuf
[0] = (char) c
; 
1208             fprintf( m_pstream
, tmpbuf 
); 
1210         else if ( c 
>= 128 ) 
1212             /* Cope with character codes > 127 */ 
1213             fprintf(m_pstream
, "\\%o", c
); 
1217             tmpbuf
[0] = (char) c
; 
1218             fprintf( m_pstream
, tmpbuf 
); 
1222     fprintf( m_pstream
, ") show\n" ); 
1224     if (m_font
.GetUnderlined()) 
1226         long uy 
= (long)(y 
+ size 
- m_underlinePosition
); 
1228         GetTextExtent(text
, &w
, &h
); 
1233                 "%ld setlinewidth\n" 
1237                 XLOG2DEV(x
), YLOG2DEV(uy
), 
1238                 (long)m_underlineThickness
, 
1239                 XLOG2DEV(x 
+ w
), YLOG2DEV(uy
) ); 
1242     CalcBoundingBox( x
, y 
); 
1243     CalcBoundingBox( x 
+ size 
* text
.Length() * 2/3 , y 
); 
1247 void wxPostScriptDC::SetBackground (const wxBrush
& brush
) 
1249     m_backgroundBrush 
= brush
; 
1252 void wxPostScriptDC::SetLogicalFunction (int WXUNUSED(function
)) 
1254     wxFAIL_MSG( wxT("wxPostScriptDC::SetLogicalFunction not implemented.") ); 
1257 void wxPostScriptDC::DoDrawSpline( wxList 
*points 
) 
1259     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1263     double a
, b
, c
, d
, x1
, y1
, x2
, y2
, x3
, y3
; 
1266     wxNode 
*node 
= points
->First(); 
1267     p 
= (wxPoint 
*)node
->Data(); 
1271     node 
= node
->Next(); 
1272     p 
= (wxPoint 
*)node
->Data(); 
1275     x3 
= a 
= (double)(x1 
+ c
) / 2; 
1276     y3 
= b 
= (double)(y1 
+ d
) / 2; 
1282             XLOG2DEV((long)x1
), YLOG2DEV((long)y1
), 
1283             XLOG2DEV((long)x3
), YLOG2DEV((long)y3
) ); 
1285     CalcBoundingBox( (long)x1
, (long)y1 
); 
1286     CalcBoundingBox( (long)x3
, (long)y3 
); 
1288     while ((node 
= node
->Next()) != NULL
) 
1290         q 
= (wxPoint 
*)node
->Data(); 
1298         x3 
= (double)(x2 
+ c
) / 2; 
1299         y3 
= (double)(y2 
+ d
) / 2; 
1302                 "%ld %ld %ld %ld %ld %ld DrawSplineSection\n", 
1303                 XLOG2DEV((long)x1
), YLOG2DEV((long)y1
), 
1304                 XLOG2DEV((long)x2
), YLOG2DEV((long)y2
), 
1305                 XLOG2DEV((long)x3
), YLOG2DEV((long)y3
) ); 
1307         CalcBoundingBox( (long)x1
, (long)y1 
); 
1308         CalcBoundingBox( (long)x3
, (long)y3 
); 
1312      At this point, (x2,y2) and (c,d) are the position of the 
1313      next-to-last and last point respectively, in the point list 
1319             XLOG2DEV((long)c
), YLOG2DEV((long)d
) ); 
1322 long wxPostScriptDC::GetCharWidth() const 
1324     // Chris Breeze: reasonable approximation using wxMODERN/Courier 
1325     return (long) (GetCharHeight() * 72.0 / 120.0); 
1329 void wxPostScriptDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
1331     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1333     m_signX 
= (xLeftRight 
? 1 : -1); 
1334     m_signY 
= (yBottomUp  
? 1 : -1); 
1336     // FIXME there is no such function in MSW 
1338     ComputeScaleAndOrigin(); 
1342 void wxPostScriptDC::SetDeviceOrigin( long x
, long y 
) 
1344     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1350     wxDC::SetDeviceOrigin( x
, h
-y 
); 
1353 void wxPostScriptDC::DoGetSize(int* width
, int* height
) const 
1355     wxPaperSize id 
= m_printData
.GetPaperId(); 
1357     wxPrintPaperType 
*paper 
= wxThePrintPaperDatabase
->FindPaperType(id
); 
1359     if (!paper
) paper 
= wxThePrintPaperDatabase
->FindPaperType(wxPAPER_A4
); 
1365         w 
= paper
->GetSizeDeviceUnits().x
; 
1366         h 
= paper
->GetSizeDeviceUnits().y
; 
1369     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1376     if (width
) *width 
= w
; 
1377     if (height
) *height 
= h
; 
1380 void wxPostScriptDC::DoGetSizeMM(int *width
, int *height
) const 
1382     wxPaperSize id 
= m_printData
.GetPaperId(); 
1384     wxPrintPaperType 
*paper 
= wxThePrintPaperDatabase
->FindPaperType(id
); 
1386     if (!paper
) paper 
= wxThePrintPaperDatabase
->FindPaperType(wxPAPER_A4
); 
1392         w 
= paper
->GetWidth() / 10; 
1393         h 
= paper
->GetHeight() / 10; 
1396     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1403     if (width
) *width 
= w
; 
1404     if (height
) *height 
= h
; 
1407 // Resolution in pixels per logical inch 
1408 wxSize 
wxPostScriptDC::GetPPI(void) const 
1410     return wxSize(72, 72); 
1414 bool wxPostScriptDC::StartDoc( const wxString
& message 
) 
1416     wxCHECK_MSG( m_ok
, FALSE
, wxT("invalid postscript dc") ); 
1418     if (m_printData
.GetFilename() == "") 
1420         wxString filename 
= wxGetTempFileName("ps"); 
1421         m_printData
.SetFilename(filename
); 
1424     m_pstream 
= fopen( m_printData
.GetFilename().fn_str(), "w+" ); 
1428         wxMessageBox( _("Cannot open file for PostScript printing!"), _("Error"), wxOK 
); 
1435     fprintf( m_pstream
, "%%%%BeginProlog\n" ); 
1436     fprintf( m_pstream
, wxPostScriptHeaderEllipse 
); 
1437     fprintf( m_pstream
, wxPostScriptHeaderEllipticArc 
); 
1438     fprintf( m_pstream
, wxPostScriptHeaderColourImage 
); 
1439     fprintf( m_pstream
, wxPostScriptHeaderReencodeISO1 
); 
1440     fprintf( m_pstream
, wxPostScriptHeaderReencodeISO2 
); 
1441     if (wxPostScriptHeaderSpline
) 
1442         fprintf( m_pstream
, wxPostScriptHeaderSpline 
); 
1443     fprintf( m_pstream
, "%%%%EndProlog\n" ); 
1445     SetBrush( *wxBLACK_BRUSH 
); 
1446     SetPen( *wxBLACK_PEN 
); 
1447     SetBackground( *wxWHITE_BRUSH 
); 
1448     SetTextForeground( *wxBLACK 
); 
1450     // set origin according to paper size 
1451     SetDeviceOrigin( 0,0 ); 
1459 void wxPostScriptDC::EndDoc () 
1461     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1466         fprintf( m_pstream
, "grestore\n" ); 
1469     fclose( m_pstream 
); 
1470     m_pstream 
= (FILE *) NULL
; 
1472     wxChar 
*header_file 
= wxGetTempFileName("ps"); 
1474     m_pstream 
= fopen( wxConvFile
.cWX2MB(header_file
) , "w+" ); 
1476     fprintf( m_pstream
, "%%!PS-Adobe-2.0\n" );                     // PostScript magic strings 
1477     fprintf( m_pstream
, "%%%%Title: %s\n", (const char *)m_title
.mb_str() ); 
1478     fprintf( m_pstream
, "%%%%Creator: %s\n", (const char*)wxConvCurrent
->cWX2MB(wxTheApp
->argv
[0]) ); 
1479     fprintf( m_pstream
, "%%%%CreationDate: %s\n", (const char *)wxNow().mb_str() ); 
1482     if ( wxGetEmailAddress(userID
, sizeof(userID
)) ) 
1484         fprintf( m_pstream
, "%%%%For: %s ", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userID
) ); 
1485         wxChar userName
[245]; 
1486         if (wxGetUserName(userName
, sizeof(userName
))) 
1487             fprintf( m_pstream
, " (%s)", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userName
) ); 
1488         fprintf( m_pstream
, "\n" ); 
1490     else if ( wxGetUserName(userID
, sizeof(userID
)) ) 
1492         fprintf( m_pstream
, "%%%%For: %s\n", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userID
) );; 
1495     // THE FOLLOWING HAS BEEN CONTRIBUTED BY Andy Fyfe <andy@hyperparallel.com> 
1497     long wx_printer_translate_x
, wx_printer_translate_y
; 
1498     double wx_printer_scale_x
, wx_printer_scale_y
; 
1500     wx_printer_translate_x 
= m_printData
.GetPrinterTranslateX(); 
1501     wx_printer_translate_y 
= m_printData
.GetPrinterTranslateY(); 
1503     wx_printer_scale_x 
= m_printData
.GetPrinterScaleX(); 
1504     wx_printer_scale_y 
= m_printData
.GetPrinterScaleY(); 
1506     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1507         fprintf( m_pstream
, "%%%%Orientation: Landscape\n" ); 
1509         fprintf( m_pstream
, "%%%%Orientation: Portrait\n" ); 
1511     // Compute the bounding box.  Note that it is in the default user 
1512     // coordinate system, thus we have to convert the values. 
1513     long llx 
= (long) ((XLOG2DEV(m_minX
)+wx_printer_translate_x
)*wx_printer_scale_x
); 
1514     long lly 
= (long) ((YLOG2DEV(m_minY
)+wx_printer_translate_y
)*wx_printer_scale_y
); 
1515     long urx 
= (long) ((XLOG2DEV(m_maxX
)+wx_printer_translate_x
)*wx_printer_scale_x
); 
1516     long ury 
= (long) ((YLOG2DEV(m_maxY
)+wx_printer_translate_y
)*wx_printer_scale_y
); 
1518     // If we're landscape, our sense of "x" and "y" is reversed. 
1519     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1522         tmp 
= llx
; llx 
= lly
; lly 
= tmp
; 
1523         tmp 
= urx
; urx 
= ury
; ury 
= tmp
; 
1525         // We need either the two lines that follow, or we need to subtract 
1526         // min_x from real_translate_y, which is commented out below. 
1527         llx 
= llx 
- (long)(m_minX
*wx_printer_scale_y
); 
1528         urx 
= urx 
- (long)(m_minX
*wx_printer_scale_y
); 
1531     // The Adobe specifications call for integers; we round as to make 
1532     // the bounding larger. 
1534             "%%%%BoundingBox: %ld %ld %ld %ld\n", 
1535             (long)floor((double)llx
), (long)floor((double)lly
), 
1536             (long)ceil((double)urx
), (long)ceil((double)ury
) ); 
1537     fprintf( m_pstream
, "%%%%Pages: %d\n", (wxPageNumber 
- 1) ); 
1538     fprintf( m_pstream
, "%%%%EndComments\n\n" ); 
1540     // To check the correctness of the bounding box, postscript commands 
1541     // to draw a box corresponding to the bounding box are generated below. 
1542     // But since we typically don't want to print such a box, the postscript 
1543     // commands are generated within comments.  These lines appear before any 
1544     // adjustment of scale, rotation, or translation, and hence are in the 
1545     // default user coordinates. 
1546     fprintf( m_pstream
, "%% newpath\n" ); 
1547     fprintf( m_pstream
, "%% %ld %ld moveto\n", llx
, lly 
); 
1548     fprintf( m_pstream
, "%% %ld %ld lineto\n", urx
, lly 
); 
1549     fprintf( m_pstream
, "%% %ld %ld lineto\n", urx
, ury 
); 
1550     fprintf( m_pstream
, "%% %ld %ld lineto closepath stroke\n", llx
, ury 
); 
1552     fclose( m_pstream 
); 
1553     m_pstream 
= (FILE*) NULL
; 
1555     wxChar 
*tmp_file 
= wxGetTempFileName("ps"); 
1557     // Paste header Before wx_printer_file 
1558     wxConcatFiles (header_file
, m_printData
.GetFilename(), tmp_file 
); 
1559     wxRemoveFile( header_file 
); 
1560     wxRemoveFile( m_printData
.GetFilename() ); 
1561     wxRenameFile( tmp_file
, m_printData
.GetFilename() ); 
1563 #if defined(__X__) || defined(__WXGTK__) 
1566         wxString 
previewCommand(m_printData
.GetPreviewCommand()); 
1567         wxString 
printerCommand(m_printData
.GetPrinterCommand()); 
1568         wxString 
printerOptions(m_printData
.GetPrinterOptions()); 
1569         wxString 
filename(m_printData
.GetFilename()); 
1571         switch (m_printData
.GetPrintMode())  
1573             case wxPRINT_MODE_PREVIEW
: 
1576                 argv
[0] = WXSTRINGCAST previewCommand
; 
1577                 argv
[1] = WXSTRINGCAST filename
; 
1578                 argv
[2] = (wxChar
*) NULL
; 
1579                 wxExecute( argv
, TRUE 
); 
1580                 wxRemoveFile( m_printData
.GetFilename() ); 
1583             case wxPRINT_MODE_PRINTER
: 
1587                 argv
[argc
++] = WXSTRINGCAST printerCommand
; 
1589                 // !SM! If we simply assign to argv[1] here, if printer options 
1590                 // are blank, we get an annoying and confusing message from lpr. 
1591                 wxChar 
*opts 
= WXSTRINGCAST printerOptions
; 
1593                     argv
[argc
++] = opts
; 
1595                 argv
[argc
++] = WXSTRINGCAST filename
; 
1596                 argv
[argc
++] = (wxChar 
*) NULL
; 
1597                 wxExecute( argv
, TRUE 
); 
1598                 wxRemoveFile( filename 
); 
1601             case wxPRINT_MODE_FILE
: 
1602             case wxPRINT_MODE_NONE
: 
1609 void wxPostScriptDC::StartPage() 
1611     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1613     fprintf( m_pstream
, "%%%%Page: %d\n", wxPageNumber
++ ); 
1615     //  What is this one supposed to do? RR. 
1616 //  *m_pstream << "matrix currentmatrix\n"; 
1618     // Added by Chris Breeze 
1620     // Each page starts with an "initgraphics" which resets the 
1621     // transformation and so we need to reset the origin 
1622     // (and rotate the page for landscape printing) 
1625     long translate_x
, translate_y
; 
1626     double scale_x
, scale_y
; 
1628     translate_x 
= m_printData
.GetPrinterTranslateX(); 
1629     translate_y 
= m_printData
.GetPrinterTranslateY(); 
1631     scale_x 
= m_printData
.GetPrinterScaleX(); 
1632     scale_y 
= m_printData
.GetPrinterScaleY(); 
1634     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1637         GetSize( (int*) NULL
, &h 
); 
1639         fprintf( m_pstream
, "90 rotate\n" ); 
1641         // I copied this one from a PostScript tutorial, but to no avail. RR. 
1642 //      fprintf( m_pstream, "90 rotate llx neg ury nef translate\n" ); 
1645     fprintf( m_pstream
, "%.8f %.8f scale\n", scale_x
, scale_y 
); 
1646     fprintf( m_pstream
, "%ld %ld translate\n", translate_x
, translate_y 
); 
1649 void wxPostScriptDC::EndPage () 
1651     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1653     fprintf( m_pstream
, "showpage\n" ); 
1656 bool wxPostScriptDC::DoBlit( long xdest
, long ydest
, 
1657                            long fwidth
, long fheight
, 
1659                            long xsrc
, long ysrc
, 
1660                            int rop
, bool WXUNUSED(useMask
) ) 
1662     wxCHECK_MSG( m_ok 
&& m_pstream
, FALSE
, wxT("invalid postscript dc") ); 
1664     wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") ); 
1666     /* blit into a bitmap */ 
1667     wxBitmap 
bitmap( (int)fwidth
, (int)fheight 
); 
1669     memDC
.SelectObject(bitmap
); 
1670     memDC
.Blit(0, 0, fwidth
, fheight
, source
, xsrc
, ysrc
, rop
); /* TODO: Blit transparently? */ 
1671     memDC
.SelectObject(wxNullBitmap
); 
1673     /* draw bitmap. scaling and positioning is done there */ 
1674     DrawBitmap( bitmap
, xdest
, ydest 
); 
1679 long wxPostScriptDC::GetCharHeight() const 
1682         return  m_font
.GetPointSize(); 
1687 void wxPostScriptDC::GetTextExtent( const wxString
& string
, long *x
, long *y
, 
1688                                     long *descent
, long *externalLeading
, wxFont 
*theFont 
) const 
1690     wxFont 
*fontToUse 
= theFont
; 
1692     if (!fontToUse
) fontToUse 
= (wxFont
*) &m_font
; 
1694     wxCHECK_RET( fontToUse
, wxT("GetTextExtent: no font defined") ); 
1695     wxCHECK_RET( x
, wxT("GetTextExtent: x == NULL") ); 
1696     wxCHECK_RET( y
, wxT("GetTextExtent: y == NULL") ); 
1698     const wxWX2MBbuf strbuf 
= string
.mb_str(); 
1700 #if !wxUSE_AFM_FOR_POSTSCRIPT 
1701     /* Provide a VERY rough estimate (avoid using it). 
1702      * Produces accurate results for mono-spaced font 
1703      * such as Courier (aka wxMODERN) */ 
1708         height 
= fontToUse
->GetPointSize(); 
1710     *x 
= strlen (strbuf
) * height 
* 72 / 120; 
1711     *y 
= (long) (height 
* 1.32);    /* allow for descender */ 
1712     if (descent
) *descent 
= 0; 
1713     if (externalLeading
) *externalLeading 
= 0; 
1716     /* method for calculating string widths in postscript: 
1717     /  read in the AFM (adobe font metrics) file for the 
1718     /  actual font, parse it and extract the character widths 
1719     /  and also the descender. this may be improved, but for now 
1720     /  it works well. the AFM file is only read in if the 
1721     /  font is changed. this may be chached in the future. 
1722     /  calls to GetTextExtent with the font unchanged are rather 
1725     /  for each font and style used there is an AFM file necessary. 
1726     /  currently i have only files for the roman font family. 
1727     /  I try to get files for the other ones! 
1729     /  CAVE: the size of the string is currently always calculated 
1730     /        in 'points' (1/72 of an inch). this should later on be 
1731     /        changed to depend on the mapping mode. 
1732     /  CAVE: the path to the AFM files must be set before calling this 
1733     /        function. this is usually done by a call like the following: 
1734     /        wxSetAFMPath("d:\\wxw161\\afm\\"); 
1738     /    wxPostScriptDC dc(NULL, TRUE); 
1740     /      wxSetAFMPath("d:\\wxw161\\afm\\"); 
1741     /      dc.StartDoc("Test"); 
1744     /      dc.SetFont(new wxFont(10, wxROMAN, wxNORMAL, wxNORMAL)); 
1745     /      dc.GetTextExtent("Hallo",&w,&h); 
1750     /  by steve (stefan.hammes@urz.uni-heidelberg.de) 
1752     /  updated: 14.05.95 */ 
1754     /* these static vars are for storing the state between calls */ 
1755     static int lastFamily
= INT_MIN
; 
1756     static int lastSize
= INT_MIN
; 
1757     static int lastStyle
= INT_MIN
; 
1758     static int lastWeight
= INT_MIN
; 
1759     static int lastDescender 
= INT_MIN
; 
1760     static int lastWidths
[256]; /* widths of the characters */ 
1762     double UnderlinePosition 
= 0.0; 
1763     double UnderlineThickness 
= 0.0; 
1765     /* get actual parameters */ 
1766     const int Family 
= fontToUse
->GetFamily(); 
1767     const int Size 
=   fontToUse
->GetPointSize(); 
1768     const int Style 
=  fontToUse
->GetStyle(); 
1769     const int Weight 
= fontToUse
->GetWeight(); 
1771     /* if we have another font, read the font-metrics */ 
1772     if (Family
!=lastFamily 
|| Size
!=lastSize 
|| Style
!=lastStyle 
|| Weight
!=lastWeight
) 
1774         /* store actual values */ 
1775         lastFamily 
= Family
; 
1778         lastWeight 
= Weight
; 
1780         char *name 
= (char*) NULL
; 
1786                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "CourBoO"; 
1787                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "CourBo"; 
1788                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "Cour0"; 
1794                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "TimesBoO"; 
1795                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "TimesBo"; 
1796                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "TimesO"; 
1797                     else name 
= "TimesRo";  
1802                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "HelvBoO"; 
1803                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "HelvBo"; 
1804                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "Helv0"; 
1810         /* get the directory of the AFM files */ 
1814         if (!m_printData
.GetFontMetricPath().IsEmpty()) 
1816             strcpy( afmName
, m_printData
.GetFontMetricPath().fn_str() ); 
1819         /* 2. open and process the file 
1820            /  a short explanation of the AFM format: 
1821            /  we have for each character a line, which gives its size 
1824            /    C 63 ; WX 444 ; N question ; B 49 -14 395 676 ; 
1826            /  that means, we have a character with ascii code 63, and width 
1827            /  (444/1000 * fontSize) points. 
1828            /  the other data is ignored for now! 
1830            /  when the font has changed, we read in the right AFM file and store the 
1831            /  character widths in an array, which is processed below (see point 3.). */ 
1833         /* new elements JC Sun Aug 25 23:21:44 MET DST 1996 */ 
1835         strcat(afmName
,name
); 
1836         strcat(afmName
,".afm"); 
1837         FILE *afmFile 
= fopen(afmName
,"r"); 
1842                  strcpy( afmName
, "/usr/local/share/wx/afm/" ); 
1843              strcat(afmName
,name
); 
1844              strcat(afmName
,".afm"); 
1845              afmFile 
= fopen(afmName
,"r"); 
1850                  strcpy( afmName
, "/usr/share/wx/afm/" ); 
1851              strcat(afmName
,name
); 
1852              strcat(afmName
,".afm"); 
1853              afmFile 
= fopen(afmName
,"r"); 
1859             wxLogDebug( "GetTextExtent: can't open AFM file '%s'\n", afmName 
); 
1860             wxLogDebug( "               using approximate values\n"); 
1861             for (int i
=0; i
<256; i
++) lastWidths
[i
] = 500; /* an approximate value */ 
1862             lastDescender 
= -150; /* dito. */ 
1866             /* init the widths array */ 
1867             for(int i
=0; i
<256; i
++) lastWidths
[i
] = INT_MIN
; 
1868             /* some variables for holding parts of a line */ 
1869             char cString
[10],semiString
[10],WXString
[10],descString
[20]; 
1870             char upString
[30], utString
[30], encString
[50]; 
1873             /* read in the file and parse it */ 
1874             while(fgets(line
,sizeof(line
),afmFile
)!=NULL
) 
1876                 /* A.) check for descender definition */ 
1877                 if (strncmp(line
,"Descender",9)==0) 
1879                     if ((sscanf(line
,"%s%d",descString
,&lastDescender
)!=2) || 
1880                             (strcmp(descString
,"Descender")!=0)) 
1882                         wxLogDebug( "AFM-file '%s': line '%s' has error (bad descender)\n", afmName
,line 
); 
1885                 /* JC 1.) check for UnderlinePosition */ 
1886                 else if(strncmp(line
,"UnderlinePosition",17)==0) 
1888                     if ((sscanf(line
,"%s%lf",upString
,&UnderlinePosition
)!=2) || 
1889                             (strcmp(upString
,"UnderlinePosition")!=0)) 
1891                         wxLogDebug( "AFM-file '%s': line '%s' has error (bad UnderlinePosition)\n", afmName
, line 
); 
1894                 /* JC 2.) check for UnderlineThickness */ 
1895                 else if(strncmp(line
,"UnderlineThickness",18)==0) 
1897                     if ((sscanf(line
,"%s%lf",utString
,&UnderlineThickness
)!=2) || 
1898                             (strcmp(utString
,"UnderlineThickness")!=0)) 
1900                         wxLogDebug( "AFM-file '%s': line '%s' has error (bad UnderlineThickness)\n", afmName
, line 
); 
1903                 /* JC 3.) check for EncodingScheme */ 
1904                 else if(strncmp(line
,"EncodingScheme",14)==0) 
1906                     if ((sscanf(line
,"%s%s",utString
,encString
)!=2) || 
1907                             (strcmp(utString
,"EncodingScheme")!=0)) 
1909                         wxLogDebug("AFM-file '%s': line '%s' has error (bad EncodingScheme)\n", afmName
, line 
); 
1911                     else if (strncmp(encString
, "AdobeStandardEncoding", 21)) 
1913                         wxLogDebug( "AFM-file '%s': line '%s' has error (unsupported EncodingScheme %s)\n", 
1914                                 afmName
,line
, encString
); 
1917                 /* B.) check for char-width */ 
1918                 else if(strncmp(line
,"C ",2)==0) 
1920                     if (sscanf(line
,"%s%d%s%s%d",cString
,&ascii
,semiString
,WXString
,&cWidth
)!=5) 
1922                         wxLogDebug("AFM-file '%s': line '%s' has an error (bad character width)\n",afmName
,line
); 
1924                     if(strcmp(cString
,"C")!=0 || strcmp(semiString
,";")!=0 || strcmp(WXString
,"WX")!=0) 
1926                         wxLogDebug("AFM-file '%s': line '%s' has a format error\n",afmName
,line
); 
1928                     /* printf("            char '%c'=%d has width '%d'\n",ascii,ascii,cWidth); */ 
1929                     if (ascii
>=0 && ascii
<256) 
1931                         lastWidths
[ascii
] = cWidth
; /* store width */ 
1935                         /* MATTHEW: this happens a lot; don't print an error */ 
1936                         /* wxLogDebug("AFM-file '%s': ASCII value %d out of range\n",afmName,ascii); */ 
1939                 /* C.) ignore other entries. */ 
1943         /* hack to compute correct values for german 'Umlaute' 
1944            /  the correct way would be to map the character names 
1945            /  like 'adieresis' to corresp. positions of ISOEnc and read 
1946            /  these values from AFM files, too. Maybe later ... */ 
1947         lastWidths
[196] = lastWidths
['A'];  // Ä 
1948         lastWidths
[228] = lastWidths
['a'];  // ä 
1949         lastWidths
[214] = lastWidths
['O'];  // Ö 
1950         lastWidths
[246] = lastWidths
['o'];  // ö 
1951         lastWidths
[220] = lastWidths
['U'];  // Ü 
1952         lastWidths
[252] = lastWidths
['u'];  // ü 
1953         lastWidths
[223] = lastWidths
[251];  // ß 
1956     /* JC: calculate UnderlineThickness/UnderlinePosition */ 
1958         // VS: dirty, but is there any better solution? 
1960         pt 
= (double*) &m_underlinePosition
; 
1961         *pt 
= UnderlinePosition 
* fontToUse
->GetPointSize() / 1000.0f
; 
1962         pt 
= (double*) &m_underlineThickness
; 
1963         *pt 
= UnderlineThickness 
* fontToUse
->GetPointSize() / 1000.0f 
* m_scaleFactor
; 
1966     /* 3. now the font metrics are read in, calc size this 
1967        /  is done by adding the widths of the characters in the 
1968        /  string. they are given in 1/1000 of the size! */ 
1971     long height
=Size
; /* by default */ 
1973     for(p
=(unsigned char *)strbuf
; *p
; p
++) 
1975         if(lastWidths
[*p
]== INT_MIN
) 
1977             wxLogDebug("GetTextExtent: undefined width for character '%c' (%d)\n", *p
,*p
); 
1978             widthSum 
+= /*(long)*/(lastWidths
[' ']/1000.0F 
* Size
); /* assume space */ 
1982             widthSum 
+= /*(long)*/((lastWidths
[*p
]/1000.0F
)*Size
); 
1986     /* add descender to height (it is usually a negative value) */ 
1987     if (lastDescender 
!= INT_MIN
) 
1989         height 
+= (long)(((-lastDescender
)/1000.0F
) * Size
); /* MATTHEW: forgot scale */ 
1992     /* return size values */ 
1993     *x 
= (long)widthSum
; 
1996     /* return other parameters */ 
1999         if(lastDescender
!=INT_MIN
) 
2001             *descent 
= (long)(((-lastDescender
)/1000.0F
) * Size
); /* MATTHEW: forgot scale */ 
2009     /* currently no idea how to calculate this! */ 
2010     if (externalLeading
) *externalLeading 
= 0; 
2015 // Determine the Default Postscript Previewer 
2016 // available on the platform 
2017 #if defined(__SUN__) && defined(__XVIEW__) 
2018 // OpenWindow/NeWS's Postscript Previewer 
2019 # define PS_VIEWER_PROG "pageview" 
2020 #elif defined(__VMS__) 
2021 #define PS_VIEWER_PROG "view/format=ps/select=x_display" 
2022 #elif defined(__SGI__) 
2023 // SGI's Display Postscript Previewer 
2024 //# define PS_VIEWER_PROG "dps" 
2025 # define PS_VIEWER_PROG "xpsview" 
2026 #elif defined(__X__) || defined(__WXGTK__) 
2027 // Front-end to ghostscript 
2028 # define PS_VIEWER_PROG "ghostview" 
2030 // Windows ghostscript/ghostview 
2031 # define PS_VIEWER_PROG "gsview" 
2034 wxPrintSetupData 
*wxThePrintSetupData 
= (wxPrintSetupData 
*) NULL
; 
2036 #if !USE_SHARED_LIBRARY 
2037 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptDC
, wxDC
) 
2038 IMPLEMENT_DYNAMIC_CLASS(wxPrintSetupData
, wxObject
) 
2041 // Redundant now I think 
2043 IMPLEMENT_CLASS(wxPostScriptPrintDialog
, wxDialog
) 
2045 wxPostScriptPrintDialog::wxPostScriptPrintDialog (wxWindow 
*parent
, const wxString
& title
, 
2046             const wxPoint
& pos
, const wxSize
& size
, long style
): 
2047    wxDialog(parent
, -1, title
, pos
, size
, style
) 
2049    wxBeginBusyCursor(); 
2054       *orientation 
= new wxString
[2], 
2055       *print_modes 
= new wxString
[3]; 
2057    long wx_printer_translate_x
, wx_printer_translate_y
; 
2058    double wx_printer_scale_x
, wx_printer_scale_y
; 
2060    orientation
[0] = _("Portrait"); 
2061    orientation
[1] = _("Landscape"); 
2063    print_modes
[0] = _("Send to Printer"); 
2064    print_modes
[1] = _("Print to File"); 
2065    print_modes
[2] = _("Preview Only"); 
2069    wxButton 
*okBut 
= new wxButton (this, wxID_OK
, _("OK"), wxPoint(5, 5)); 
2070    (void) new wxButton (this, wxID_CANCEL
, _("Cancel"), wxPoint(40, 5)); 
2071    okBut
->SetDefault(); 
2074 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
2075    (void) new wxStaticText( this, -1, _("Printer Command: "), 
2077    (void) new wxTextCtrl( this, wxID_PRINTER_COMMAND
, wxThePrintSetupData
->GetPrinterCommand(), 
2078                           wxPoint(100, yPos
), wxSize(100, -1) ); 
2080    (void) new wxStaticText( this, -1, _("Printer Options: "), 
2081                             wxPoint(210, yPos
) ); 
2082    (void) new wxTextCtrl( this, wxID_PRINTER_OPTIONS
, wxThePrintSetupData
->GetPrinterOptions(), 
2083                           wxPoint(305, yPos
), wxSize(150, -1) ); 
2089    wxRadioBox 
*radio0 
= new wxRadioBox(this, wxID_PRINTER_ORIENTATION
, "Orientation: ", wxPoint(5, yPos
), wxSize(-1,-1), 
2090                                        2,orientation
,2,wxRA_SPECIFY_ROWS
); 
2091    radio0
->SetSelection((int)wxThePrintSetupData
->GetPrinterOrientation() - 1); 
2093   // @@@ Configuration hook 
2094    if ( !wxThePrintSetupData
->GetPrintPreviewCommand() ) 
2095       wxThePrintSetupData
->SetPrintPreviewCommand(PS_VIEWER_PROG
); 
2097    //   wxGetResource ("wxWindows", "PSView", &wxThePrintSetupData->m_previewCommand); 
2099    features 
= (wxThePrintSetupData
->GetPrintPreviewCommand() && 
2100                *wxThePrintSetupData
->GetPrintPreviewCommand()) ? 3 : 2; 
2102    wxRadioBox 
*radio1 
= new wxRadioBox(this, wxID_PRINTER_MODES
, _("PostScript:"), 
2104                                        wxSize(-1,-1), features
, 
2105                                        print_modes
, features
, wxRA_SPECIFY_ROWS
); 
2108    radio1
->Enable(0, FALSE
); 
2109    if (wxThePrintSetupData
->GetPrintPreviewCommand() && *wxThePrintSetupData
->GetPrintPreviewCommand()) 
2110       radio1
->Enable(2, FALSE
); 
2113    radio1
->SetSelection((int)wxThePrintSetupData
->GetPrinterMode()); 
2114    wxThePrintSetupData
->GetPrinterTranslation(&wx_printer_translate_x
, &wx_printer_translate_y
); 
2115    wxThePrintSetupData
->GetPrinterScaling(&wx_printer_scale_x
, &wx_printer_scale_y
); 
2117    sprintf (buf
, "%.2f", wx_printer_scale_x
); 
2120    (void) new wxStaticText(this, -1, _("X Scaling"), wxPoint(5, yPos
)); 
2121    /* wxTextCtrl *text1 = */ (void) new wxTextCtrl(this, wxID_PRINTER_X_SCALE
, buf
, wxPoint(100, yPos
), wxSize(100, -1)); 
2123    sprintf (buf
, "%.2f", wx_printer_scale_y
); 
2124    (void) new wxStaticText(this, -1, _("Y Scaling"), wxPoint(220, yPos
)); 
2125    /* wxTextCtrl *text2 = */ (void) new wxTextCtrl(this, wxID_PRINTER_Y_SCALE
, buf
, wxPoint(320, yPos
), wxSize(100, -1)); 
2129    (void) new wxStaticText(this, -1, _("X Translation"), wxPoint(5, yPos
)); 
2130    sprintf (buf
, "%.2ld", wx_printer_translate_x
); 
2131    /* wxTextCtrl *text3 = */ (void) new wxTextCtrl(this, wxID_PRINTER_X_TRANS
, buf
, wxPoint(100, yPos
), wxSize(100, -1)); 
2133    (void) new wxStaticText(this, -1, _("Y Translation"), wxPoint(220, yPos
)); 
2134    sprintf (buf
, "%.2ld", wx_printer_translate_y
); 
2135    /* wxTextCtrl *text4 = */ (void) new wxTextCtrl(this, wxID_PRINTER_Y_TRANS
, buf
, wxPoint(320, yPos
), wxSize(100, -1)); 
2139    delete[] orientation
; 
2140    delete[] print_modes
; 
2145 int wxPostScriptPrintDialog::ShowModal () 
2147   if ( wxDialog::ShowModal() == wxID_OK 
) 
2149 //    wxTextCtrl *text0 = (wxTextCtrl *)FindWindow(wxID_PRINTER_OPTIONS); 
2150       wxTextCtrl 
*text1 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_X_SCALE
); 
2151       wxTextCtrl 
*text2 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_Y_SCALE
); 
2152       wxTextCtrl 
*text3 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_X_TRANS
); 
2153       wxTextCtrl 
*text4 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_Y_TRANS
); 
2154 //    wxTextCtrl *text_prt = (wxTextCtrl *)FindWindow(wxID_PRINTER_COMMAND); 
2155       wxRadioBox 
*radio0 
= (wxRadioBox 
*)FindWindow(wxID_PRINTER_ORIENTATION
); 
2156       wxRadioBox 
*radio1 
= (wxRadioBox 
*)FindWindow(wxID_PRINTER_MODES
); 
2158       StringToDouble (WXSTRINGCAST text1
->GetValue (), &wxThePrintSetupData
->m_printerScaleX
); 
2159       StringToDouble (WXSTRINGCAST text2
->GetValue (), &wxThePrintSetupData
->m_printerScaleY
); 
2160       StringToLong (WXSTRINGCAST text3
->GetValue (), &wxThePrintSetupData
->m_printerTranslateX
); 
2161       StringToLong (WXSTRINGCAST text4
->GetValue (), &wxThePrintSetupData
->m_printerTranslateY
); 
2164       //      wxThePrintSetupData->SetPrinterOptions(WXSTRINGCAST text0->GetValue ()); 
2165       //      wxThePrintSetupData->SetPrinterCommand(WXSTRINGCAST text_prt->GetValue ()); 
2168       wxThePrintSetupData
->SetPrinterOrientation((radio0
->GetSelection() == 1 ? wxLANDSCAPE 
: wxPORTRAIT
)); 
2171       switch ( radio1
->GetSelection() ) { 
2172         case 0: wxThePrintSetupData
->SetPrinterMode(PS_PRINTER
); break; 
2173         case 1:  wxThePrintSetupData
->SetPrinterMode(PS_FILE
); break; 
2174         case 2: wxThePrintSetupData
->SetPrinterMode(PS_PREVIEW
); break; 
2183 // PostScript printer settings 
2184 // RETAINED FOR BACKWARD COMPATIBILITY 
2185 void wxSetPrinterCommand(const wxString
& cmd
) 
2187   wxThePrintSetupData
->SetPrinterCommand(cmd
); 
2190 void wxSetPrintPreviewCommand(const wxString
& cmd
) 
2192   wxThePrintSetupData
->SetPrintPreviewCommand(cmd
); 
2195 void wxSetPrinterOptions(const wxString
& flags
) 
2197   wxThePrintSetupData
->SetPrinterOptions(flags
); 
2200 void wxSetPrinterFile(const wxString
& f
) 
2202   wxThePrintSetupData
->SetPrinterFile(f
); 
2205 void wxSetPrinterOrientation(int orient
) 
2207   wxThePrintSetupData
->SetPrinterOrientation(orient
); 
2210 void wxSetPrinterScaling(double x
, double y
) 
2212   wxThePrintSetupData
->SetPrinterScaling(x
, y
); 
2215 void wxSetPrinterTranslation(long x
, long y
) 
2217   wxThePrintSetupData
->SetPrinterTranslation(x
, y
); 
2220 // 1 = Preview, 2 = print to file, 3 = send to printer 
2221 void wxSetPrinterMode(int mode
) 
2223   wxThePrintSetupData
->SetPrinterMode(mode
); 
2226 void wxSetAFMPath(const wxString
& f
) 
2228   wxThePrintSetupData
->SetAFMPath(f
); 
2231 // Get current values 
2232 wxString 
wxGetPrinterCommand() 
2234   return wxThePrintSetupData
->GetPrinterCommand(); 
2237 wxString 
wxGetPrintPreviewCommand() 
2239   return wxThePrintSetupData
->GetPrintPreviewCommand(); 
2242 wxString 
wxGetPrinterOptions() 
2244   return wxThePrintSetupData
->GetPrinterOptions(); 
2247 wxString 
wxGetPrinterFile() 
2249   return wxThePrintSetupData
->GetPrinterFile(); 
2252 int wxGetPrinterOrientation() 
2254   return wxThePrintSetupData
->GetPrinterOrientation(); 
2257 void wxGetPrinterScaling(double* x
, double* y
) 
2259   wxThePrintSetupData
->GetPrinterScaling(x
, y
); 
2262 void wxGetPrinterTranslation(long *x
, long *y
) 
2264   wxThePrintSetupData
->GetPrinterTranslation(x
, y
); 
2267 int wxGetPrinterMode() 
2269   return wxThePrintSetupData
->GetPrinterMode(); 
2272 wxString 
wxGetAFMPath() 
2274   return wxThePrintSetupData
->GetAFMPath(); 
2281 wxPrintSetupData::wxPrintSetupData() 
2283   m_printerOrient 
= wxPORTRAIT
; 
2284   m_printerScaleX 
= (double)1.0; 
2285   m_printerScaleY 
= (double)1.0; 
2286   m_printerTranslateX 
= 0; 
2287   m_printerTranslateY 
= 0; 
2288   m_printerMode 
= wxPRINT_MODE_FILE
; 
2289   m_printColour 
= TRUE
; 
2292 wxPrintSetupData::~wxPrintSetupData() 
2296 void wxPrintSetupData::operator=(wxPrintSetupData
& data
) 
2298   SetPrinterCommand(data
.GetPrinterCommand()); 
2299   SetPrintPreviewCommand(data
.GetPrintPreviewCommand()); 
2300   SetPrinterOptions(data
.GetPrinterOptions()); 
2302   data
.GetPrinterTranslation(&x
, &y
); 
2303   SetPrinterTranslation(x
, y
); 
2306   data
.GetPrinterScaling(&x1
, &y1
); 
2307   SetPrinterScaling(x1
, y1
); 
2309   SetPrinterOrientation(data
.GetPrinterOrientation()); 
2310   SetPrinterMode(data
.GetPrinterMode()); 
2311   SetAFMPath(data
.GetAFMPath()); 
2312   SetPaperName(data
.GetPaperName()); 
2313   SetColour(data
.GetColour()); 
2316 // Initialize from a wxPrintData object (wxPrintData should now be used instead of wxPrintSetupData). 
2317 void wxPrintSetupData::operator=(const wxPrintData
& data
) 
2319     SetPrinterCommand(data
.GetPrinterCommand()); 
2320     SetPrintPreviewCommand(data
.GetPreviewCommand()); 
2321     SetPrinterOptions(data
.GetPrinterOptions()); 
2322     SetPrinterTranslation(data
.GetPrinterTranslateX(), data
.GetPrinterTranslateY()); 
2323     SetPrinterScaling(data
.GetPrinterScaleX(), data
.GetPrinterScaleY()); 
2324     SetPrinterOrientation(data
.GetOrientation()); 
2325     SetPrinterMode((int) data
.GetPrintMode()); 
2326     SetAFMPath(data
.GetFontMetricPath()); 
2327     SetPaperName(wxThePrintPaperDatabase
->ConvertIdToName(data
.GetPaperId())); 
2328     SetColour(data
.GetColour()); 
2329     SetPrinterFile(data
.GetFilename()); 
2332 void wxInitializePrintSetupData(bool init
) 
2336     wxThePrintSetupData 
= new wxPrintSetupData
; 
2338     wxThePrintSetupData
->SetPrintPreviewCommand(PS_VIEWER_PROG
); 
2339     wxThePrintSetupData
->SetPrinterOrientation(wxPORTRAIT
); 
2340     wxThePrintSetupData
->SetPrinterMode(wxPRINT_MODE_PREVIEW
); 
2341     wxThePrintSetupData
->SetPaperName(_("A4 sheet, 210 x 297 mm")); 
2343     // Could have a .ini file to read in some defaults 
2344     // - and/or use environment variables, e.g. WXWIN 
2346     wxThePrintSetupData
->SetPrinterCommand("print"); 
2347     wxThePrintSetupData
->SetPrinterOptions("/nonotify/queue=psqueue"); 
2348     wxThePrintSetupData
->SetAFMPath("sys$ps_font_metrics:"); 
2351     wxThePrintSetupData
->SetPrinterCommand("print"); 
2352     wxThePrintSetupData
->SetAFMPath("c:\\windows\\system\\"); 
2353     wxThePrintSetupData
->SetPrinterOptions(""); 
2355 #if !defined(__VMS__) && !defined(__WXMSW__) 
2356     wxThePrintSetupData
->SetPrinterCommand("lpr"); 
2357     wxThePrintSetupData
->SetPrinterOptions(""); 
2358     wxThePrintSetupData
->SetAFMPath(""); 
2363     if (wxThePrintSetupData
) 
2364       delete wxThePrintSetupData
; 
2365      wxThePrintSetupData 
= (wxPrintSetupData 
*) NULL
; 
2369 // A module to allow initialization/cleanup of PostScript-related 
2370 // things without calling these functions from app.cpp. 
2372 class WXDLLEXPORT wxPostScriptModule
: public wxModule
 
2374 DECLARE_DYNAMIC_CLASS(wxPostScriptModule
) 
2376     wxPostScriptModule() {} 
2381 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptModule
, wxModule
) 
2384  * Initialization/cleanup module 
2387 bool wxPostScriptModule::OnInit() 
2389     wxInitializePrintSetupData(); 
2394 void wxPostScriptModule::OnExit() 
2396     wxInitializePrintSetupData(FALSE
); 
2403   // wxUSE_PRINTING_ARCHITECTURE