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 "dcpsg.h" 
  16 #include "wx/wxprec.h" 
  25 #if wxUSE_PRINTING_ARCHITECTURE 
  31 #include "wx/window.h" 
  32 #include "wx/dcmemory.h" 
  35 #include "wx/filedlg.h" 
  37 #include "wx/msgdlg.h" 
  40 #include "wx/generic/dcpsg.h" 
  41 #include "wx/printdlg.h" 
  42 #include "wx/button.h" 
  43 #include "wx/stattext.h" 
  44 #include "wx/radiobox.h" 
  45 #include "wx/textctrl.h" 
  46 #include "wx/prntbase.h" 
  48 #include "wx/filefn.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 float wxPostScriptDC::ms_PSScaleFactor 
= 10.0; 
 237 void wxPostScriptDC::SetResolution(int ppi
) 
 239     ms_PSScaleFactor 
= (float)ppi 
/ 72.0; 
 242 int wxPostScriptDC::GetResolution() 
 244     return (int)(ms_PSScaleFactor 
* 72.0); 
 249 wxPostScriptDC::wxPostScriptDC () 
 251     m_pstream 
= (FILE*) NULL
; 
 261     m_underlinePosition 
= 0.0; 
 262     m_underlineThickness 
= 0.0; 
 264     m_signX 
=  1;  // default x-axis left to right 
 265     m_signY 
= -1;  // default y-axis bottom up -> top down 
 267     // Compatibility only 
 268     // HH: Doesn't seem to work for wxMSW... 
 269     #if !defined(__WXMSW__) 
 270     m_printData 
= * wxThePrintSetupData
; 
 274 wxPostScriptDC::wxPostScriptDC (const wxString
& file
, bool interactive
, wxWindow 
*parent
) 
 276     m_pstream 
= (FILE*) NULL
; 
 286     m_underlinePosition 
= 0.0; 
 287     m_underlineThickness 
= 0.0; 
 289     m_signX 
=  1;  // default x-axis left to right 
 290     m_signY 
= -1;  // default y-axis bottom up -> top down 
 292     Create(file
, interactive
, parent
); 
 295 bool wxPostScriptDC::Create(const wxString
& file
, bool interactive
, wxWindow 
*parent
) 
 297     m_isInteractive 
= interactive
; 
 300     m_printData
.SetFilename(file
); 
 303     // Can only send to file in Windows 
 304     m_printData
.SetPrintMode(wxPRINT_MODE_FILE
); 
 309         if ((m_ok 
= PrinterDialog (parent
) ) == FALSE
) return FALSE
; 
 319 wxPostScriptDC::wxPostScriptDC (const wxPrintData
& printData
) 
 321     m_pstream 
= (FILE*) NULL
; 
 331     m_underlinePosition 
= 0.0; 
 332     m_underlineThickness 
= 0.0; 
 334     m_signX 
=  1;  // default x-axis left to right 
 335     m_signY 
= -1;  // default y-axis bottom up -> top down 
 337     m_printData 
= printData
; 
 342 wxPostScriptDC::~wxPostScriptDC () 
 347         m_pstream 
= (FILE*) NULL
; 
 351 bool wxPostScriptDC::Ok() const 
 356 // This dialog is deprecated now: use wxGenericPrintDialog or the printing framework 
 357 bool wxPostScriptDC::PrinterDialog(wxWindow 
*parent
) 
 359     wxPostScriptPrintDialog 
dialog( parent
, _("Printer Settings"), wxPoint(150, 150), wxSize(400, 400), 
 360                                     wxDEFAULT_DIALOG_STYLE 
| wxDIALOG_MODAL 
); 
 361     m_ok 
= (dialog
.ShowModal () == wxID_OK
); 
 363     if (!m_ok
) return FALSE
; 
 365     if ((m_printData
.GetFilename() == "") && 
 366         (m_printData
.GetPrintMode() == wxPRINT_MODE_PREVIEW  
|| 
 367          m_printData
.GetPrintMode() == wxPRINT_MODE_PRINTER
)) 
 371       m_printData
.SetFilename("preview"); 
 373       // For PS_PRINTER action this depends on a Unix-style print spooler 
 374       // since the wx_printer_file can be destroyed during a session 
 375       // @@@ TODO: a Windows-style answer for non-Unix 
 377       wxGetUserId (userId
, sizeof (userId
) / sizeof (char)); 
 379       wxStrcpy (tmp
, wxT("/tmp/preview_")); 
 380       wxStrcat (tmp
, userId
); 
 381       m_printData
.SetFilename(tmp
); 
 384       wxStrcpy(tmp2
, m_printData
.GetFilename()); 
 385       wxStrcat (tmp2
, wxT(".ps")); 
 386       m_printData
.SetFilename(tmp2
); 
 388     else if ((m_printData
.GetFilename() == wxT("")) && (m_printData
.GetPrintMode() == wxPRINT_MODE_FILE
)) 
 390       wxString file 
= wxSaveFileSelector (_("PostScript"), wxT("ps")); 
 391       if ( file
.IsEmpty() ) 
 397       m_printData
.SetFilename(file
); 
 404 void wxPostScriptDC::DoSetClippingRegion (wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
 406     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 408     if (m_clipping
) DestroyClippingRegion(); 
 410     wxDC::DoSetClippingRegion(x
, y
, w
, h
); 
 419             "closepath clip newpath\n", 
 420             LogicalToDeviceX(x
),   LogicalToDeviceY(y
), 
 421             LogicalToDeviceX(x
+w
), LogicalToDeviceY(y
), 
 422             LogicalToDeviceX(x
+w
), LogicalToDeviceY(y
+h
), 
 423             LogicalToDeviceX(x
),   LogicalToDeviceY(y
+h
) ); 
 427 void wxPostScriptDC::DestroyClippingRegion() 
 429     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 434         fprintf( m_pstream
, "grestore\n" ); 
 437     wxDC::DestroyClippingRegion(); 
 440 void wxPostScriptDC::Clear() 
 442     wxFAIL_MSG( wxT("wxPostScriptDC::Clear not implemented.") ); 
 445 bool wxPostScriptDC::DoFloodFill (wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
), const wxColour 
&WXUNUSED(col
), int WXUNUSED(style
)) 
 447     wxFAIL_MSG( wxT("wxPostScriptDC::FloodFill not implemented.") ); 
 451 bool wxPostScriptDC::DoGetPixel (wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
), wxColour 
* WXUNUSED(col
)) const 
 453     wxFAIL_MSG( wxT("wxPostScriptDC::GetPixel not implemented.") ); 
 457 void wxPostScriptDC::DoCrossHair (wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
)) 
 459     wxFAIL_MSG( wxT("wxPostScriptDC::CrossHair not implemented.") ); 
 462 void wxPostScriptDC::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
) 
 464     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 466     if  (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 475             LogicalToDeviceX(x1
), LogicalToDeviceY(y1
), 
 476             LogicalToDeviceX(x2
), LogicalToDeviceY (y2
) ); 
 478     CalcBoundingBox( x1
, y1 
); 
 479     CalcBoundingBox( x2
, y2 
); 
 482 #define RAD2DEG 57.29577951308 
 484 void wxPostScriptDC::DoDrawArc (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
) 
 486     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 488     wxCoord dx 
= x1 
- xc
; 
 489     wxCoord dy 
= y1 
- yc
; 
 490     wxCoord radius 
= (wxCoord
) sqrt( (double)(dx
*dx
+dy
*dy
) ); 
 491     double alpha1
, alpha2
; 
 493     if (x1 
== x2 
&& y1 
== y2
) 
 498     else if (radius 
== 0.0) 
 500         alpha1 
= alpha2 
= 0.0; 
 504         alpha1 
= (x1 
- xc 
== 0) ? 
 505             (y1 
- yc 
< 0) ? 90.0 : -90.0 : 
 506                 -atan2(double(y1
-yc
), double(x1
-xc
)) * RAD2DEG
; 
 507         alpha2 
= (x2 
- xc 
== 0) ? 
 508             (y2 
- yc 
< 0) ? 90.0 : -90.0 : 
 509                 -atan2(double(y2
-yc
), double(x2
-xc
)) * RAD2DEG
; 
 511     while (alpha1 
<= 0)   alpha1 
+= 360; 
 512     while (alpha2 
<= 0)   alpha2 
+= 360; // adjust angles to be between 
 513     while (alpha1 
> 360)  alpha1 
-= 360; // 0 and 360 degree 
 514     while (alpha2 
> 360)  alpha2 
-= 360; 
 516     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 522                 "%d %d %d %d %d %d ellipse\n" 
 526                 LogicalToDeviceX(xc
), LogicalToDeviceY(yc
), LogicalToDeviceXRel(radius
), LogicalToDeviceYRel(radius
), (wxCoord
)alpha1
, (wxCoord
) alpha2
, 
 527                 LogicalToDeviceX(xc
), LogicalToDeviceY(yc
) ); 
 529         CalcBoundingBox( xc
-radius
, yc
-radius 
); 
 530         CalcBoundingBox( xc
+radius
, yc
+radius 
); 
 533     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 539                 "%d %d %d %d %d %d ellipse\n" 
 543                 LogicalToDeviceX(xc
), LogicalToDeviceY(yc
), LogicalToDeviceXRel(radius
), LogicalToDeviceYRel(radius
), (wxCoord
)alpha1
, (wxCoord
) alpha2
, 
 544                 LogicalToDeviceX(xc
), LogicalToDeviceY(yc
) ); 
 546         CalcBoundingBox( xc
-radius
, yc
-radius 
); 
 547         CalcBoundingBox( xc
+radius
, yc
+radius 
); 
 551 void wxPostScriptDC::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
) 
 553     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 555     if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360; 
 556     if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360; 
 562         DrawEllipse(x
,y
,w
,h
); 
 566     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 572                 "%d %d %d %d %d %d true ellipticarc\n", 
 573                 LogicalToDeviceX(x
+w
/2), LogicalToDeviceY(y
+h
/2), LogicalToDeviceXRel(w
/2), LogicalToDeviceYRel(h
/2), (wxCoord
)sa
, (wxCoord
)ea 
); 
 575         CalcBoundingBox( x 
,y 
); 
 576         CalcBoundingBox( x
+w
, y
+h 
); 
 579     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 585                 "%d %d %d %d %d %d false ellipticarc\n", 
 586                 LogicalToDeviceX(x
+w
/2), LogicalToDeviceY(y
+h
/2), LogicalToDeviceXRel(w
/2), LogicalToDeviceYRel(h
/2), (wxCoord
)sa
, (wxCoord
)ea 
); 
 588         CalcBoundingBox( x 
,y 
); 
 589         CalcBoundingBox( x
+w
, y
+h 
); 
 593 void wxPostScriptDC::DoDrawPoint (wxCoord x
, wxCoord y
) 
 595     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 597     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 606             LogicalToDeviceX(x
),   LogicalToDeviceY(y
), 
 607             LogicalToDeviceX(x
+1), LogicalToDeviceY(y
) ); 
 609     CalcBoundingBox( x
, y 
); 
 612 void wxPostScriptDC::DoDrawPolygon (int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
)) 
 614     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 618     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 622         fprintf( m_pstream
, "newpath\n" ); 
 624         wxCoord xx 
= LogicalToDeviceX(points
[0].x 
+ xoffset
); 
 625         wxCoord yy 
= LogicalToDeviceY(points
[0].y 
+ yoffset
); 
 627         fprintf( m_pstream
, "%d %d moveto\n", xx
, yy 
); 
 629         CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 631         for (int i 
= 1; i 
< n
; i
++) 
 633             xx 
= LogicalToDeviceX(points
[i
].x 
+ xoffset
); 
 634             yy 
= LogicalToDeviceY(points
[i
].y 
+ yoffset
); 
 636             fprintf( m_pstream
, "%d %d lineto\n", xx
, yy 
); 
 638             CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 641         fprintf( m_pstream
, "fill\n" ); 
 644     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 648         fprintf( m_pstream
, "newpath\n" ); 
 650         wxCoord xx 
= LogicalToDeviceX(points
[0].x 
+ xoffset
); 
 651         wxCoord yy 
= LogicalToDeviceY(points
[0].y 
+ yoffset
); 
 653         fprintf( m_pstream
, "%d %d moveto\n", xx
, yy 
); 
 655         CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 657         for (int i 
= 1; i 
< n
; i
++) 
 659             xx 
= LogicalToDeviceX(points
[i
].x 
+ xoffset
); 
 660             yy 
= LogicalToDeviceY(points
[i
].y 
+ yoffset
); 
 662             fprintf( m_pstream
, "%d %d lineto\n", xx
, yy 
); 
 664             CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 667         fprintf( m_pstream
, "closepath\n" ); 
 668         fprintf( m_pstream
, "stroke\n" ); 
 672 void wxPostScriptDC::DoDrawLines (int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
) 
 674     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 676     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 683     for ( i 
=0; i
<n 
; i
++ ) 
 685         CalcBoundingBox( LogicalToDeviceX(points
[i
].x
+xoffset
), LogicalToDeviceY(points
[i
].y
+yoffset
)); 
 691             LogicalToDeviceX(points
[0].x
+xoffset
), LogicalToDeviceY(points
[0].y
+yoffset
) ); 
 693     for (i 
= 1; i 
< n
; i
++) 
 697                 LogicalToDeviceX(points
[i
].x
+xoffset
), LogicalToDeviceY(points
[i
].y
+yoffset
) ); 
 700     fprintf( m_pstream
, "stroke\n" ); 
 703 void wxPostScriptDC::DoDrawRectangle (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 705     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 707     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 719                 LogicalToDeviceX(x
),         LogicalToDeviceY(y
), 
 720                 LogicalToDeviceX(x 
+ width
), LogicalToDeviceY(y
), 
 721                 LogicalToDeviceX(x 
+ width
), LogicalToDeviceY(y 
+ height
), 
 722                 LogicalToDeviceX(x
),         LogicalToDeviceY(y 
+ height
) ); 
 724         CalcBoundingBox( x
, y 
); 
 725         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 728     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 740                 LogicalToDeviceX(x
),         LogicalToDeviceY(y
), 
 741                 LogicalToDeviceX(x 
+ width
), LogicalToDeviceY(y
), 
 742                 LogicalToDeviceX(x 
+ width
), LogicalToDeviceY(y 
+ height
), 
 743                 LogicalToDeviceX(x
),         LogicalToDeviceY(y 
+ height
) ); 
 745         CalcBoundingBox( x
, y 
); 
 746         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 750 void wxPostScriptDC::DoDrawRoundedRectangle (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
) 
 752     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 756         // Now, a negative radius is interpreted to mean 
 757         // 'the proportion of the smallest X or Y dimension' 
 758         double smallest 
= 0.0; 
 763         radius 
=  (-radius 
* smallest
); 
 766     wxCoord rad 
= (wxCoord
) radius
; 
 768     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 772         /* Draw rectangle anticlockwise */ 
 775                 "%d %d %d 90 180 arc\n" 
 777                 "%d %d %d 180 270 arc\n" 
 779                 "%d %d %d 270 0 arc\n" 
 781                 "%d %d %d 0 90 arc\n" 
 785                 LogicalToDeviceX(x 
+ rad
), LogicalToDeviceY(y 
+ rad
), LogicalToDeviceXRel(rad
), 
 786                 LogicalToDeviceX(x
), LogicalToDeviceY(y 
+ rad
), 
 787                 LogicalToDeviceX(x 
+ rad
), LogicalToDeviceY(y 
+ height 
- rad
), LogicalToDeviceXRel(rad
), 
 788                 LogicalToDeviceX(x 
+ width 
- rad
), LogicalToDeviceY(y 
+ height
), 
 789                 LogicalToDeviceX(x 
+ width 
- rad
), LogicalToDeviceY(y 
+ height 
- rad
), LogicalToDeviceXRel(rad
), 
 790                 LogicalToDeviceX(x 
+ width
), LogicalToDeviceY(y 
+ rad
), 
 791                 LogicalToDeviceX(x 
+ width 
- rad
), LogicalToDeviceY(y 
+ rad
), LogicalToDeviceXRel(rad
), 
 792                 LogicalToDeviceX(x 
+ rad
), LogicalToDeviceY(y
) ); 
 794         CalcBoundingBox( x
, y 
); 
 795         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 798     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 802         /* Draw rectangle anticlockwise */ 
 805                 "%d %d %d 90 180 arc\n" 
 807                 "%d %d %d 180 270 arc\n" 
 809                 "%d %d %d 270 0 arc\n" 
 811                 "%d %d %d 0 90 arc\n" 
 815                 LogicalToDeviceX(x 
+ rad
), LogicalToDeviceY(y 
+ rad
), LogicalToDeviceXRel(rad
), 
 816                 LogicalToDeviceX(x
), LogicalToDeviceY(y 
+ rad
), 
 817                 LogicalToDeviceX(x 
+ rad
), LogicalToDeviceY(y 
+ height 
- rad
), LogicalToDeviceXRel(rad
), 
 818                 LogicalToDeviceX(x 
+ width 
- rad
), LogicalToDeviceY(y 
+ height
), 
 819                 LogicalToDeviceX(x 
+ width 
- rad
), LogicalToDeviceY(y 
+ height 
- rad
), LogicalToDeviceXRel(rad
), 
 820                 LogicalToDeviceX(x 
+ width
), LogicalToDeviceY(y 
+ rad
), 
 821                 LogicalToDeviceX(x 
+ width 
- rad
), LogicalToDeviceY(y 
+ rad
), LogicalToDeviceXRel(rad
), 
 822                 LogicalToDeviceX(x 
+ rad
), LogicalToDeviceY(y
) ); 
 824         CalcBoundingBox( x
, y 
); 
 825         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 829 void wxPostScriptDC::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 831     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 833     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 839                 "%d %d %d %d 0 360 ellipse\n" 
 841                 LogicalToDeviceX(x 
+ width 
/ 2), LogicalToDeviceY(y 
+ height 
/ 2), 
 842                 LogicalToDeviceXRel(width 
/ 2), LogicalToDeviceYRel(height 
/ 2) ); 
 844         CalcBoundingBox( x 
- width
, y 
- height 
); 
 845         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 848     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 854                 "%d %d %d %d 0 360 ellipse\n" 
 856                 LogicalToDeviceX(x 
+ width 
/ 2), LogicalToDeviceY(y 
+ height 
/ 2), 
 857                 LogicalToDeviceXRel(width 
/ 2), LogicalToDeviceYRel(height 
/ 2) ); 
 859         CalcBoundingBox( x 
- width
, y 
- height 
); 
 860         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 864 void wxPostScriptDC::DoDrawIcon( const wxIcon
& icon
, wxCoord x
, wxCoord y 
) 
 866     DrawBitmap( icon
, x
, y
, TRUE 
); 
 869 /* this has to be char, not wxChar */ 
 870 static char hexArray
[] = "0123456789ABCDEF"; 
 871 static void LocalDecToHex( int dec
, char *buf 
) 
 873     int firstDigit 
= (int)(dec
/16.0); 
 874     int secondDigit 
= (int)(dec 
- (firstDigit
*16.0)); 
 875     buf
[0] = hexArray
[firstDigit
]; 
 876     buf
[1] = hexArray
[secondDigit
]; 
 880 void wxPostScriptDC::DoDrawBitmap( const wxBitmap
& bitmap
, wxCoord x
, wxCoord y
, bool WXUNUSED(useMask
) ) 
 882     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 884     if (!bitmap
.Ok()) return; 
 886     wxImage image 
= bitmap
.ConvertToImage(); 
 888     if (!image
.Ok()) return; 
 890     wxCoord w 
= image
.GetWidth(); 
 891     wxCoord h 
= image
.GetHeight(); 
 893     wxCoord ww 
= LogicalToDeviceXRel(image
.GetWidth()); 
 894     wxCoord hh 
= LogicalToDeviceYRel(image
.GetHeight()); 
 896     wxCoord xx 
= LogicalToDeviceX(x
); 
 897     wxCoord yy 
= LogicalToDeviceY(y 
+ bitmap
.GetHeight()); 
 900             "/origstate save def\n" 
 902             "/pix %d string def\n" 
 903             "/grays %d string def\n" 
 910             "{currentfile pix readhexstring pop}\n" 
 911             "false 3 colorimage\n", 
 912             w
, w
, xx
, yy
, ww
, hh
, w
, h
, w
, -h
, h 
); 
 915     for (int j 
= 0; j 
< h
; j
++) 
 917         for (int i 
= 0; i 
< w
; i
++) 
 920             LocalDecToHex( image
.GetRed(i
,j
), buffer 
); 
 921             fprintf( m_pstream
, buffer 
); 
 922             LocalDecToHex( image
.GetGreen(i
,j
), buffer 
); 
 923             fprintf( m_pstream
, buffer 
); 
 924             LocalDecToHex( image
.GetBlue(i
,j
), buffer 
); 
 925             fprintf( m_pstream
, buffer 
); 
 927         fprintf( m_pstream
, "\n" ); 
 930     fprintf( m_pstream
, "end\n" ); 
 931     fprintf( m_pstream
, "origstate restore\n" ); 
 934 void wxPostScriptDC::SetFont( const wxFont
& font 
) 
 936     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 938     if (!font
.Ok())  return; 
 942     int Style 
= m_font
.GetStyle(); 
 943     int Weight 
= m_font
.GetWeight(); 
 946     switch (m_font
.GetFamily()) 
 951             if (Style 
== wxITALIC
) 
 953                 if (Weight 
== wxBOLD
) 
 954                     name 
= "/Courier-BoldOblique"; 
 956                     name 
= "/Courier-Oblique"; 
 960                 if (Weight 
== wxBOLD
) 
 961                     name 
= "/Courier-Bold"; 
 969             if (Style 
== wxITALIC
) 
 971                 if (Weight 
== wxBOLD
) 
 972                     name 
= "/Times-BoldItalic"; 
 974                     name 
= "/Times-Italic"; 
 978                 if (Weight 
== wxBOLD
) 
 979                     name 
= "/Times-Bold"; 
 981                     name 
= "/Times-Roman"; 
 987             name 
= "/ZapfChancery-MediumItalic"; 
 995             if (Style 
== wxITALIC
) 
 997                 if (Weight 
== wxBOLD
) 
 998                     name 
= "/Helvetica-BoldOblique"; 
1000                     name 
= "/Helvetica-Oblique"; 
1004                 if (Weight 
== wxBOLD
) 
1005                     name 
= "/Helvetica-Bold"; 
1007                     name 
= "/Helvetica"; 
1013     fprintf( m_pstream
, name 
); 
1014     fprintf( m_pstream
, " reencodeISO def\n" ); 
1015     fprintf( m_pstream
, name 
); 
1016     fprintf( m_pstream
, " findfont\n" ); 
1019     sprintf( buffer
, "%f scalefont setfont\n", LogicalToDeviceYRel(m_font
.GetPointSize() * 1000) / 1000.0F
); 
1020                 // this is a hack - we must scale font size (in pts) according to m_scaleY but 
1021                 // LogicalToDeviceYRel works with wxCoord type (int or longint). Se we first convert font size 
1022                 // to 1/1000th of pt and then back. 
1023     for (int i 
= 0; i 
< 100; i
++) 
1024         if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1025     fprintf( m_pstream
, buffer 
); 
1028 void wxPostScriptDC::SetPen( const wxPen
& pen 
) 
1030     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1032     if (!pen
.Ok()) return; 
1034     int oldStyle 
= m_pen
.GetStyle(); 
1041         sprintf( buffer
, "%f setlinewidth\n", LogicalToDeviceXRel(1000 * m_pen
.GetWidth()) / 1000.0f 
); 
1043         sprintf( buffer
, "%f setlinewidth\n", LogicalToDeviceXRel(1000 * m_pen
.GetWidth()) / 1000.0f 
); 
1045         for (int i 
= 0; i 
< 100; i
++) 
1046             if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1047         fprintf( m_pstream
, buffer 
); 
1051      Line style - WRONG: 2nd arg is OFFSET 
1053      Here, I'm afraid you do not conceive meaning of parameters of 'setdash' 
1054      operator correctly. You should look-up this in the Red Book: the 2nd parame- 
1055      ter is not number of values in the array of the first one, but an offset 
1056      into this description of the pattern. I mean a real *offset* not index 
1057      into array. I.e. If the command is [3 4] 1 setdash   is used, then there 
1058      will be first black line *2* units wxCoord, then space 4 units, then the 
1059      pattern of *3* units black, 4 units space will be repeated. 
1062     static const char *dotted 
= "[2 5] 2"; 
1063     static const char *short_dashed 
= "[4 4] 2"; 
1064     static const char *wxCoord_dashed 
= "[4 8] 2"; 
1065     static const char *dotted_dashed 
= "[6 6 2 6] 4"; 
1067     const char *psdash 
= (char *) NULL
; 
1068     switch (m_pen
.GetStyle()) 
1070         case wxDOT
:           psdash 
= dotted
;         break; 
1071         case wxSHORT_DASH
:    psdash 
= short_dashed
;   break; 
1072         case wxLONG_DASH
:     psdash 
= wxCoord_dashed
;    break; 
1073         case wxDOT_DASH
:      psdash 
= dotted_dashed
;  break; 
1076         default:              psdash 
= "[] 0";         break; 
1079     if (oldStyle 
!= m_pen
.GetStyle()) 
1081         fprintf( m_pstream
, psdash 
); 
1082         fprintf( m_pstream
," setdash\n" ); 
1086     unsigned char red 
= m_pen
.GetColour().Red(); 
1087     unsigned char blue 
= m_pen
.GetColour().Blue(); 
1088     unsigned char green 
= m_pen
.GetColour().Green(); 
1092         // Anything not white is black 
1093         if (! (red 
== (unsigned char) 255 && 
1094                blue 
== (unsigned char) 255 && 
1095                green 
== (unsigned char) 255) ) 
1097             red 
= (unsigned char) 0; 
1098             green 
= (unsigned char) 0; 
1099             blue 
= (unsigned char) 0; 
1104     if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1106         double redPS 
= (double)(red
) / 255.0; 
1107         double bluePS 
= (double)(blue
) / 255.0; 
1108         double greenPS 
= (double)(green
) / 255.0; 
1112                 "%.8f %.8f %.8f setrgbcolor\n", 
1113                 redPS
, greenPS
, bluePS 
); 
1114         for (int i 
= 0; i 
< 100; i
++) 
1115             if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1116         fprintf( m_pstream
, buffer 
); 
1119         m_currentBlue 
= blue
; 
1120         m_currentGreen 
= green
; 
1124 void wxPostScriptDC::SetBrush( const wxBrush
& brush 
) 
1126     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1128     if (!brush
.Ok()) return; 
1133     unsigned char red 
= m_brush
.GetColour().Red(); 
1134     unsigned char blue 
= m_brush
.GetColour().Blue(); 
1135     unsigned char green 
= m_brush
.GetColour().Green(); 
1139         // Anything not white is black 
1140         if (! (red 
== (unsigned char) 255 && 
1141                blue 
== (unsigned char) 255 && 
1142                green 
== (unsigned char) 255) ) 
1144             red 
= (unsigned char) 0; 
1145             green 
= (unsigned char) 0; 
1146             blue 
= (unsigned char) 0; 
1151     if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1153         double redPS 
= (double)(red
) / 255.0; 
1154         double bluePS 
= (double)(blue
) / 255.0; 
1155         double greenPS 
= (double)(green
) / 255.0; 
1159                 "%.8f %.8f %.8f setrgbcolor\n", 
1160                 redPS
, greenPS
, bluePS 
); 
1161         for (int i 
= 0; i 
< 100; i
++) 
1162             if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1163         fprintf( m_pstream
, buffer 
); 
1166         m_currentBlue 
= blue
; 
1167         m_currentGreen 
= green
; 
1173 #include "wx/gtk/private.h" 
1174 #include "wx/fontutil.h" 
1175 #include "gtk/gtk.h" 
1176 #include <pango/pangoft2.h> 
1180 void wxPostScriptDC::DoDrawText( const wxString
& text
, wxCoord x
, wxCoord y 
) 
1182     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1187     PangoContext 
*context 
= pango_ft2_get_context (150, 150); 
1189     // What are these for? 
1190     pango_context_set_language (context
, pango_language_from_string ("en_US")); 
1191     pango_context_set_base_dir (context
, PANGO_DIRECTION_LTR 
); 
1194     pango_context_set_font_description (context
, m_font
.GetNativeFontInfo()->description 
); 
1197     PangoLayout 
*layout 
= layout 
= pango_layout_new (context
); 
1199     wxCharBuffer buffer 
= wxConvUTF8
.cWC2MB( text 
); 
1201     wxCharBuffer buffer 
= wxConvUTF8
.cWC2MB( wxConvLocal
.cWX2WC( text 
) ); 
1203         pango_layout_set_text( layout
, (const char*) buffer
, strlen(buffer
) ); 
1205     // Find out extent for the bitmap 
1208     PangoRectangle logical_rect
; 
1209     pango_layout_get_extents (layout
, NULL
, &logical_rect
); 
1210     height 
= PANGO_PIXELS (logical_rect
.height
); 
1211     width 
= PANGO_PIXELS (logical_rect
.width
); 
1213     // Allocate FreeType 2 bitmap 
1214     int byte_width 
= (width 
+ 7)/8 * 8; 
1216     guchar 
*buf 
= (guchar
*) g_malloc (byte_width 
* height
); 
1217     memset (buf
, 0x00, byte_width 
* height
); 
1218     bitmap
.rows 
= height
; 
1219     bitmap
.width 
= byte_width
; 
1220         bitmap
.pitch 
= byte_width
; 
1221         bitmap
.buffer 
= buf
; 
1222         bitmap
.num_grays 
= 256; 
1223         bitmap
.pixel_mode 
= ft_pixel_mode_grays
; 
1226         pango_ft2_render_layout (&bitmap
, layout
, 0, 0); 
1228         // Invert bitmap to get black text on white background 
1229     for (int pix_idx 
= 0; pix_idx 
< width 
* height
; pix_idx
++) 
1230         buf
[pix_idx
] = 255-buf
[pix_idx
]; 
1233     wxCoord xx 
= LogicalToDeviceX(x
); 
1234     wxCoord yy 
= LogicalToDeviceY(y 
/*+ bitmap.GetHeight()*/ ); 
1236     fprintf(m_pstream
, "gsave\n"); 
1237     fprintf(m_pstream
, "%d %d translate\n", xx
, yy
); 
1238     fprintf(m_pstream
, "/img_width %d def\n", bitmap
.width
); 
1239     fprintf(m_pstream
, "/img_height %d def\n", bitmap
.rows
); 
1240     fprintf(m_pstream
, "/picstr img_width 8 idiv string def\n"); 
1243           "  img_width 72 150 div mul\n" 
1244           "  img_height 72 150 div mul scale\n" 
1246           "  img_width img_height\n" 
1248           "  [img_width 0 0 img_height neg 0 img_height 0.67 mul]\n" 
1250           "    picstr readhexstring pop }\n" 
1255     for (int b_idx
= 0; b_idx 
< bitmap
.width
/8 * bitmap
.rows
; b_idx
++) 
1257       guchar packed_b 
= 0; 
1260       if (b_idx 
% (bitmap
.width
/8) == 0) 
1261         fprintf(m_pstream
, "\n"); 
1263       for (bit_idx 
= 0; bit_idx 
< 8; bit_idx
++) 
1265           guchar this_bit 
= bitmap
.buffer
[b_idx 
* 8+bit_idx
]>128; 
1266           packed_b 
= (packed_b 
<< 1) + this_bit
; 
1270       fprintf(m_pstream
, "%02x", packed_b
); 
1273     fprintf(m_pstream
, "\ngrestore\n" ); 
1280     wxCoord text_w
, text_h
, text_descent
; 
1282     GetTextExtent(text
, &text_w
, &text_h
, &text_descent
); 
1284     // VZ: this seems to be unnecessary, so taking it out for now, if it 
1285     //     doesn't create any problems, remove this comment entirely 
1286     //SetFont( m_font ); 
1288     if (m_textForegroundColour
.Ok()) 
1290         unsigned char red 
= m_textForegroundColour
.Red(); 
1291         unsigned char blue 
= m_textForegroundColour
.Blue(); 
1292         unsigned char green 
= m_textForegroundColour
.Green(); 
1296             // Anything not white is black 
1297             if (! (red 
== (unsigned char) 255 && 
1298                         blue 
== (unsigned char) 255 && 
1299                         green 
== (unsigned char) 255)) 
1301                 red 
= (unsigned char) 0; 
1302                 green 
= (unsigned char) 0; 
1303                 blue 
= (unsigned char) 0; 
1307         // maybe setgray here ? 
1308         if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1310             double redPS 
= (double)(red
) / 255.0; 
1311             double bluePS 
= (double)(blue
) / 255.0; 
1312             double greenPS 
= (double)(green
) / 255.0; 
1316                 "%.8f %.8f %.8f setrgbcolor\n", 
1317                 redPS
, greenPS
, bluePS 
); 
1318             for (int i 
= 0; i 
< 100; i
++) 
1319                 if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1320             fprintf( m_pstream
, buffer 
); 
1323             m_currentBlue 
= blue
; 
1324             m_currentGreen 
= green
; 
1328     int size 
= m_font
.GetPointSize(); 
1330 //    wxCoord by = y + (wxCoord)floor( double(size) * 2.0 / 3.0 ); // approximate baseline 
1331 //    commented by V. Slavik and replaced by accurate version 
1332 //        - note that there is still rounding error in text_descent! 
1333     wxCoord by 
= y 
+ size 
- text_descent
; // baseline 
1334     fprintf( m_pstream
, "%d %d moveto\n", LogicalToDeviceX(x
), LogicalToDeviceY(by
) ); 
1336     fprintf( m_pstream
, "(" ); 
1337     const wxWX2MBbuf textbuf 
= text
.mb_str(); 
1338     size_t len 
= strlen(textbuf
); 
1340     for (i 
= 0; i 
< len
; i
++) 
1342         int c 
= (unsigned char) textbuf
[i
]; 
1343         if (c 
== ')' || c 
== '(' || c 
== '\\') 
1345             /* Cope with special characters */ 
1346             fprintf( m_pstream
, "\\" ); 
1347             fputc(c
, m_pstream
); 
1349         else if ( c 
>= 128 ) 
1351             /* Cope with character codes > 127 */ 
1352             fprintf(m_pstream
, "\\%o", c
); 
1356             fputc(c
, m_pstream
); 
1360     fprintf( m_pstream
, ") show\n" ); 
1362     if (m_font
.GetUnderlined()) 
1364         wxCoord uy 
= (wxCoord
)(y 
+ size 
- m_underlinePosition
); 
1374                 LogicalToDeviceX(x
), LogicalToDeviceY(uy
), 
1375                 m_underlineThickness
, 
1376                 LogicalToDeviceX(x 
+ text_w
), LogicalToDeviceY(uy
) ); 
1377         for (i 
= 0; i 
< 100; i
++) 
1378             if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1379         fprintf( m_pstream
, buffer 
); 
1382     CalcBoundingBox( x
, y 
); 
1383     CalcBoundingBox( x 
+ size 
* text
.Length() * 2/3 , y 
); 
1387 void wxPostScriptDC::DoDrawRotatedText( const wxString
& text
, wxCoord x
, wxCoord y
, double angle 
) 
1391         DoDrawText(text
, x
, y
); 
1395     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1399     if (m_textForegroundColour
.Ok()) 
1401         unsigned char red 
= m_textForegroundColour
.Red(); 
1402         unsigned char blue 
= m_textForegroundColour
.Blue(); 
1403         unsigned char green 
= m_textForegroundColour
.Green(); 
1407             // Anything not white is black 
1408             if (! (red 
== (unsigned char) 255 && 
1409                    blue 
== (unsigned char) 255 && 
1410                    green 
== (unsigned char) 255)) 
1412                 red 
= (unsigned char) 0; 
1413                 green 
= (unsigned char) 0; 
1414                 blue 
= (unsigned char) 0; 
1418         // maybe setgray here ? 
1419         if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1421             double redPS 
= (double)(red
) / 255.0; 
1422             double bluePS 
= (double)(blue
) / 255.0; 
1423             double greenPS 
= (double)(green
) / 255.0; 
1427                 "%.8f %.8f %.8f setrgbcolor\n", 
1428                 redPS
, greenPS
, bluePS 
); 
1429             for (int i 
= 0; i 
< 100; i
++) 
1430                 if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1431             fprintf( m_pstream
, buffer 
); 
1434             m_currentBlue 
= blue
; 
1435             m_currentGreen 
= green
; 
1439     int size 
= m_font
.GetPointSize(); 
1441     long by 
= y 
+ (long)floor( double(size
) * 2.0 / 3.0 ); // approximate baseline 
1443     // FIXME only correct for 90 degrees 
1444     fprintf(m_pstream
, "%d %d moveto\n", 
1445             LogicalToDeviceX((wxCoord
)(x 
+ size
)), LogicalToDeviceY((wxCoord
)by
) ); 
1448     sprintf(buffer
, "%.8f rotate\n", angle
); 
1450     for (i 
= 0; i 
< 100; i
++) 
1451         if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1452     fprintf(m_pstream
, buffer
); 
1454     fprintf( m_pstream
, "(" ); 
1455     const wxWX2MBbuf textbuf 
= text
.mb_str(); 
1456     size_t len 
= strlen(textbuf
); 
1457     for (i 
= 0; i 
< len
; i
++) 
1459         int c 
= (unsigned char) textbuf
[i
]; 
1460         if (c 
== ')' || c 
== '(' || c 
== '\\') 
1462             /* Cope with special characters */ 
1463             fprintf( m_pstream
, "\\" ); 
1464             fputc(c
, m_pstream
); 
1466         else if ( c 
>= 128 ) 
1468             /* Cope with character codes > 127 */ 
1469             fprintf(m_pstream
, "\\%o", c
); 
1473             fputc(c
, m_pstream
); 
1477     fprintf( m_pstream
, ") show\n" ); 
1479     sprintf( buffer
, "%.8f rotate\n", -angle 
); 
1480     for (i 
= 0; i 
< 100; i
++) 
1481         if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1482     fprintf( m_pstream
, buffer 
); 
1484     if (m_font
.GetUnderlined()) 
1486         wxCoord uy 
= (wxCoord
)(y 
+ size 
- m_underlinePosition
); 
1489         GetTextExtent(text
, &w
, &h
); 
1498                  LogicalToDeviceX(x
), LogicalToDeviceY(uy
), 
1499                  m_underlineThickness
, 
1500                  LogicalToDeviceX(x 
+ w
), LogicalToDeviceY(uy
) ); 
1501         for (i 
= 0; i 
< 100; i
++) 
1502             if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1503         fprintf( m_pstream
, buffer 
); 
1506     CalcBoundingBox( x
, y 
); 
1507     CalcBoundingBox( x 
+ size 
* text
.Length() * 2/3 , y 
); 
1510 void wxPostScriptDC::SetBackground (const wxBrush
& brush
) 
1512     m_backgroundBrush 
= brush
; 
1515 void wxPostScriptDC::SetLogicalFunction (int WXUNUSED(function
)) 
1517     wxFAIL_MSG( wxT("wxPostScriptDC::SetLogicalFunction not implemented.") ); 
1520 void wxPostScriptDC::DoDrawSpline( wxList 
*points 
) 
1522     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1526     double a
, b
, c
, d
, x1
, y1
, x2
, y2
, x3
, y3
; 
1529     wxNode 
*node 
= points
->First(); 
1530     p 
= (wxPoint 
*)node
->Data(); 
1534     node 
= node
->Next(); 
1535     p 
= (wxPoint 
*)node
->Data(); 
1538     x3 
= a 
= (double)(x1 
+ c
) / 2; 
1539     y3 
= b 
= (double)(y1 
+ d
) / 2; 
1545             LogicalToDeviceX((wxCoord
)x1
), LogicalToDeviceY((wxCoord
)y1
), 
1546             LogicalToDeviceX((wxCoord
)x3
), LogicalToDeviceY((wxCoord
)y3
) ); 
1548     CalcBoundingBox( (wxCoord
)x1
, (wxCoord
)y1 
); 
1549     CalcBoundingBox( (wxCoord
)x3
, (wxCoord
)y3 
); 
1551     while ((node 
= node
->Next()) != NULL
) 
1553         q 
= (wxPoint 
*)node
->Data(); 
1561         x3 
= (double)(x2 
+ c
) / 2; 
1562         y3 
= (double)(y2 
+ d
) / 2; 
1565                 "%d %d %d %d %d %d DrawSplineSection\n", 
1566                 LogicalToDeviceX((wxCoord
)x1
), LogicalToDeviceY((wxCoord
)y1
), 
1567                 LogicalToDeviceX((wxCoord
)x2
), LogicalToDeviceY((wxCoord
)y2
), 
1568                 LogicalToDeviceX((wxCoord
)x3
), LogicalToDeviceY((wxCoord
)y3
) ); 
1570         CalcBoundingBox( (wxCoord
)x1
, (wxCoord
)y1 
); 
1571         CalcBoundingBox( (wxCoord
)x3
, (wxCoord
)y3 
); 
1575        At this point, (x2,y2) and (c,d) are the position of the 
1576        next-to-last and last point respectively, in the point list 
1582             LogicalToDeviceX((wxCoord
)c
), LogicalToDeviceY((wxCoord
)d
) ); 
1585 wxCoord 
wxPostScriptDC::GetCharWidth() const 
1587     // Chris Breeze: reasonable approximation using wxMODERN/Courier 
1588     return (wxCoord
) (GetCharHeight() * 72.0 / 120.0); 
1592 void wxPostScriptDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
1594     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1596     m_signX 
= (xLeftRight 
? 1 : -1); 
1597     m_signY 
= (yBottomUp  
? 1 : -1); 
1599     // FIXME there is no such function in MSW nor in OS2/PM 
1600 #if !defined(__WXMSW__) && !defined(__WXPM__) 
1601     ComputeScaleAndOrigin(); 
1605 void wxPostScriptDC::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
1607     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1613     wxDC::SetDeviceOrigin( x
, h
-y 
); 
1616 void wxPostScriptDC::DoGetSize(int* width
, int* height
) const 
1618     wxPaperSize id 
= m_printData
.GetPaperId(); 
1620     wxPrintPaperType 
*paper 
= wxThePrintPaperDatabase
->FindPaperType(id
); 
1622     if (!paper
) paper 
= wxThePrintPaperDatabase
->FindPaperType(wxPAPER_A4
); 
1628         w 
= paper
->GetSizeDeviceUnits().x
; 
1629         h 
= paper
->GetSizeDeviceUnits().y
; 
1632     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1639     if (width
) *width 
= (int)(w 
* ms_PSScaleFactor
); 
1640     if (height
) *height 
= (int)(h 
* ms_PSScaleFactor
); 
1643 void wxPostScriptDC::DoGetSizeMM(int *width
, int *height
) const 
1645     wxPaperSize id 
= m_printData
.GetPaperId(); 
1647     wxPrintPaperType 
*paper 
= wxThePrintPaperDatabase
->FindPaperType(id
); 
1649     if (!paper
) paper 
= wxThePrintPaperDatabase
->FindPaperType(wxPAPER_A4
); 
1655         w 
= paper
->GetWidth() / 10; 
1656         h 
= paper
->GetHeight() / 10; 
1659     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1666     if (width
) *width 
= w
; 
1667     if (height
) *height 
= h
; 
1670 // Resolution in pixels per logical inch 
1671 wxSize 
wxPostScriptDC::GetPPI(void) const 
1673     return wxSize((int)(72 * ms_PSScaleFactor
), 
1674                   (int)(72 * ms_PSScaleFactor
)); 
1678 bool wxPostScriptDC::StartDoc( const wxString
& message 
) 
1680     wxCHECK_MSG( m_ok
, FALSE
, wxT("invalid postscript dc") ); 
1682     if (m_printData
.GetFilename() == "") 
1684         wxString filename 
= wxGetTempFileName("ps"); 
1685         m_printData
.SetFilename(filename
); 
1688     m_pstream 
= wxFopen( m_printData
.GetFilename().c_str(), wxT("w+") );  // FIXME: use fn_str() here under Unicode? 
1692         wxLogError( _("Cannot open file for PostScript printing!")); 
1699     fprintf( m_pstream
, "%%%%BeginProlog\n" ); 
1700     fprintf( m_pstream
, wxPostScriptHeaderEllipse 
); 
1701     fprintf( m_pstream
, wxPostScriptHeaderEllipticArc 
); 
1702     fprintf( m_pstream
, wxPostScriptHeaderColourImage 
); 
1703     fprintf( m_pstream
, wxPostScriptHeaderReencodeISO1 
); 
1704     fprintf( m_pstream
, wxPostScriptHeaderReencodeISO2 
); 
1705     if (wxPostScriptHeaderSpline
) 
1706         fprintf( m_pstream
, wxPostScriptHeaderSpline 
); 
1707     fprintf( m_pstream
, "%%%%EndProlog\n" ); 
1709     SetBrush( *wxBLACK_BRUSH 
); 
1710     SetPen( *wxBLACK_PEN 
); 
1711     SetBackground( *wxWHITE_BRUSH 
); 
1712     SetTextForeground( *wxBLACK 
); 
1714     // set origin according to paper size 
1715     SetDeviceOrigin( 0,0 ); 
1723 void wxPostScriptDC::EndDoc () 
1725     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1730         fprintf( m_pstream
, "grestore\n" ); 
1733     fclose( m_pstream 
); 
1734     m_pstream 
= (FILE *) NULL
; 
1736     wxChar 
*header_file 
= wxGetTempFileName("ps"); 
1738     m_pstream 
= fopen( wxConvFile
.cWX2MB(header_file
) , "w+" ); 
1740     fprintf( m_pstream
, "%%!PS-Adobe-2.0\n" );                     // PostScript magic strings 
1741     fprintf( m_pstream
, "%%%%Title: %s\n", (const char *)m_title
.mb_str() ); 
1742     fprintf( m_pstream
, "%%%%Creator: %s\n", (const char*)wxConvCurrent
->cWX2MB(wxTheApp
->argv
[0]) ); 
1743     fprintf( m_pstream
, "%%%%CreationDate: %s\n", (const char *)wxNow().mb_str() ); 
1746     if ( wxGetEmailAddress(userID
, sizeof(userID
)) ) 
1748         fprintf( m_pstream
, "%%%%For: %s ", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userID
) ); 
1749         wxChar userName
[245]; 
1750         if (wxGetUserName(userName
, sizeof(userName
))) 
1751             fprintf( m_pstream
, " (%s)", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userName
) ); 
1752         fprintf( m_pstream
, "\n" ); 
1754     else if ( wxGetUserName(userID
, sizeof(userID
)) ) 
1756         fprintf( m_pstream
, "%%%%For: %s\n", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userID
) );; 
1759     // THE FOLLOWING HAS BEEN CONTRIBUTED BY Andy Fyfe <andy@hyperparallel.com> 
1761     wxCoord wx_printer_translate_x
, wx_printer_translate_y
; 
1762     double wx_printer_scale_x
, wx_printer_scale_y
; 
1764     wx_printer_translate_x 
= (wxCoord
)m_printData
.GetPrinterTranslateX(); 
1765     wx_printer_translate_y 
= (wxCoord
)m_printData
.GetPrinterTranslateY(); 
1767     wx_printer_scale_x 
= m_printData
.GetPrinterScaleX(); 
1768     wx_printer_scale_y 
= m_printData
.GetPrinterScaleY(); 
1770     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1771         fprintf( m_pstream
, "%%%%Orientation: Landscape\n" ); 
1773         fprintf( m_pstream
, "%%%%Orientation: Portrait\n" ); 
1775     // Compute the bounding box.  Note that it is in the default user 
1776     // coordinate system, thus we have to convert the values. 
1777     wxCoord minX 
= (wxCoord
) LogicalToDeviceX(m_minX
); 
1778     wxCoord minY 
= (wxCoord
) LogicalToDeviceY(m_minY
); 
1779     wxCoord maxX 
= (wxCoord
) LogicalToDeviceX(m_maxX
); 
1780     wxCoord maxY 
= (wxCoord
) LogicalToDeviceY(m_maxY
); 
1782     // LOG2DEV may have changed the minimum to maximum vice versa 
1783     if ( minX 
> maxX 
) { wxCoord tmp 
= minX
; minX 
= maxX
; maxX 
= tmp
; } 
1784     if ( minY 
> maxY 
) { wxCoord tmp 
= minY
; minY 
= maxY
; maxY 
= tmp
; } 
1786     // account for used scaling (boundingbox is before scaling in ps-file) 
1787     double scale_x 
= m_printData
.GetPrinterScaleX() / ms_PSScaleFactor
; 
1788     double scale_y 
= m_printData
.GetPrinterScaleY() / ms_PSScaleFactor
; 
1790     wxCoord llx
, lly
, urx
, ury
; 
1791     llx 
= (wxCoord
) ((minX
+wx_printer_translate_x
)*scale_x
); 
1792     lly 
= (wxCoord
) ((minY
+wx_printer_translate_y
)*scale_y
); 
1793     urx 
= (wxCoord
) ((maxX
+wx_printer_translate_x
)*scale_x
); 
1794     ury 
= (wxCoord
) ((maxY
+wx_printer_translate_y
)*scale_y
); 
1795     // (end of bounding box computation) 
1798     // If we're landscape, our sense of "x" and "y" is reversed. 
1799     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1802         tmp 
= llx
; llx 
= lly
; lly 
= tmp
; 
1803         tmp 
= urx
; urx 
= ury
; ury 
= tmp
; 
1805         // We need either the two lines that follow, or we need to subtract 
1806         // min_x from real_translate_y, which is commented out below. 
1807         llx 
= llx 
- (wxCoord
)(m_minX
*wx_printer_scale_y
); 
1808         urx 
= urx 
- (wxCoord
)(m_minX
*wx_printer_scale_y
); 
1811     // The Adobe specifications call for integers; we round as to make 
1812     // the bounding larger. 
1814             "%%%%BoundingBox: %d %d %d %d\n", 
1815             (wxCoord
)floor((double)llx
), (wxCoord
)floor((double)lly
), 
1816             (wxCoord
)ceil((double)urx
), (wxCoord
)ceil((double)ury
) ); 
1817     fprintf( m_pstream
, "%%%%Pages: %d\n", (wxPageNumber 
- 1) ); 
1818     fprintf( m_pstream
, "%%%%EndComments\n\n" ); 
1820     // To check the correctness of the bounding box, postscript commands 
1821     // to draw a box corresponding to the bounding box are generated below. 
1822     // But since we typically don't want to print such a box, the postscript 
1823     // commands are generated within comments.  These lines appear before any 
1824     // adjustment of scale, rotation, or translation, and hence are in the 
1825     // default user coordinates. 
1826     fprintf( m_pstream
, "%% newpath\n" ); 
1827     fprintf( m_pstream
, "%% %d %d moveto\n", llx
, lly 
); 
1828     fprintf( m_pstream
, "%% %d %d lineto\n", urx
, lly 
); 
1829     fprintf( m_pstream
, "%% %d %d lineto\n", urx
, ury 
); 
1830     fprintf( m_pstream
, "%% %d %d lineto closepath stroke\n", llx
, ury 
); 
1832     fclose( m_pstream 
); 
1833     m_pstream 
= (FILE*) NULL
; 
1835     wxChar 
*tmp_file 
= wxGetTempFileName("ps"); 
1837     // Paste header Before wx_printer_file 
1838     wxConcatFiles (header_file
, m_printData
.GetFilename(), tmp_file 
); 
1839     wxRemoveFile( header_file 
); 
1840     wxRemoveFile( m_printData
.GetFilename() ); 
1841     wxRenameFile( tmp_file
, m_printData
.GetFilename() ); 
1843 #if defined(__X__) || defined(__WXGTK__) 
1846         wxString 
previewCommand(m_printData
.GetPreviewCommand()); 
1847         wxString 
printerCommand(m_printData
.GetPrinterCommand()); 
1848         wxString 
printerOptions(m_printData
.GetPrinterOptions()); 
1849         wxString 
filename(m_printData
.GetFilename()); 
1851         switch (m_printData
.GetPrintMode()) 
1853             case wxPRINT_MODE_PREVIEW
: 
1856                 argv
[0] = WXSTRINGCAST previewCommand
; 
1857                 argv
[1] = WXSTRINGCAST filename
; 
1858                 argv
[2] = (wxChar
*) NULL
; 
1859 #if defined(__WXGTK20__) && wxUSE_UNICODE 
1861                 wxExecute( argv
, TRUE 
); 
1863                 wxRemoveFile( m_printData
.GetFilename() ); 
1866             case wxPRINT_MODE_PRINTER
: 
1870                 argv
[argc
++] = WXSTRINGCAST printerCommand
; 
1872                 // !SM! If we simply assign to argv[1] here, if printer options 
1873                 // are blank, we get an annoying and confusing message from lpr. 
1874                 wxChar 
*opts 
= WXSTRINGCAST printerOptions
; 
1876                     argv
[argc
++] = opts
; 
1878                 argv
[argc
++] = WXSTRINGCAST filename
; 
1879                 argv
[argc
++] = (wxChar 
*) NULL
; 
1880 #if defined(__WXGTK20__) && wxUSE_UNICODE 
1882                 wxExecute( argv
, TRUE 
); 
1884                 wxRemoveFile( filename 
); 
1887             case wxPRINT_MODE_FILE
: 
1888             case wxPRINT_MODE_NONE
: 
1895 void wxPostScriptDC::StartPage() 
1897     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1899     fprintf( m_pstream
, "%%%%Page: %d\n", wxPageNumber
++ ); 
1901     //  What is this one supposed to do? RR. 
1902 //  *m_pstream << "matrix currentmatrix\n"; 
1904     // Added by Chris Breeze 
1906     // Each page starts with an "initgraphics" which resets the 
1907     // transformation and so we need to reset the origin 
1908     // (and rotate the page for landscape printing) 
1911     wxCoord translate_x
, translate_y
; 
1912     double scale_x
, scale_y
; 
1914     translate_x 
= (wxCoord
)m_printData
.GetPrinterTranslateX(); 
1915     translate_y 
= (wxCoord
)m_printData
.GetPrinterTranslateY(); 
1917     scale_x 
= m_printData
.GetPrinterScaleX(); 
1918     scale_y 
= m_printData
.GetPrinterScaleY(); 
1920     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1923         GetSize( (int*) NULL
, &h 
); 
1925         fprintf( m_pstream
, "90 rotate\n" ); 
1927         // I copied this one from a PostScript tutorial, but to no avail. RR. 
1928         // fprintf( m_pstream, "90 rotate llx neg ury nef translate\n" ); 
1932     sprintf( buffer
, "%.8f %.8f scale\n", scale_x 
/ ms_PSScaleFactor
, 
1933                                           scale_y 
/ ms_PSScaleFactor
); 
1934     for (int i 
= 0; i 
< 100; i
++) 
1935         if (buffer
[i
] == ',') buffer
[i
] = '.'; 
1936     fprintf( m_pstream
, buffer 
); 
1938     fprintf( m_pstream
, "%d %d translate\n", translate_x
, translate_y 
); 
1941 void wxPostScriptDC::EndPage () 
1943     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1945     fprintf( m_pstream
, "showpage\n" ); 
1948 bool wxPostScriptDC::DoBlit( wxCoord xdest
, wxCoord ydest
, 
1949                            wxCoord fwidth
, wxCoord fheight
, 
1951                            wxCoord xsrc
, wxCoord ysrc
, 
1952                            int rop
, bool WXUNUSED(useMask
), wxCoord 
WXUNUSED(xsrcMask
), wxCoord 
WXUNUSED(ysrcMask
) ) 
1954     wxCHECK_MSG( m_ok 
&& m_pstream
, FALSE
, wxT("invalid postscript dc") ); 
1956     wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") ); 
1958     /* blit into a bitmap */ 
1959     wxBitmap 
bitmap( (int)fwidth
, (int)fheight 
); 
1961     memDC
.SelectObject(bitmap
); 
1962     memDC
.Blit(0, 0, fwidth
, fheight
, source
, xsrc
, ysrc
, rop
); /* TODO: Blit transparently? */ 
1963     memDC
.SelectObject(wxNullBitmap
); 
1965     /* draw bitmap. scaling and positioning is done there */ 
1966     DrawBitmap( bitmap
, xdest
, ydest 
); 
1971 wxCoord 
wxPostScriptDC::GetCharHeight() const 
1974         return m_font
.GetPointSize(); 
1979 void wxPostScriptDC::DoGetTextExtent(const wxString
& string
, 
1980                                      wxCoord 
*x
, wxCoord 
*y
, 
1981                                      wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1982                                      wxFont 
*theFont 
) const 
1984     wxFont 
*fontToUse 
= theFont
; 
1986     if (!fontToUse
) fontToUse 
= (wxFont
*) &m_font
; 
1988     wxCHECK_RET( fontToUse
, wxT("GetTextExtent: no font defined") ); 
1990     const wxWX2MBbuf strbuf 
= string
.mb_str(); 
1992 #if !wxUSE_AFM_FOR_POSTSCRIPT 
1993     /* Provide a VERY rough estimate (avoid using it). 
1994      * Produces accurate results for mono-spaced font 
1995      * such as Courier (aka wxMODERN) */ 
2000         height 
= fontToUse
->GetPointSize(); 
2003         *x 
= strlen (strbuf
) * height 
* 72 / 120; 
2005         *y 
= (wxCoord
) (height 
* 1.32);    /* allow for descender */ 
2006     if (descent
) *descent 
= 0; 
2007     if (externalLeading
) *externalLeading 
= 0; 
2010     /* method for calculating string widths in postscript: 
2011     /  read in the AFM (adobe font metrics) file for the 
2012     /  actual font, parse it and extract the character widths 
2013     /  and also the descender. this may be improved, but for now 
2014     /  it works well. the AFM file is only read in if the 
2015     /  font is changed. this may be chached in the future. 
2016     /  calls to GetTextExtent with the font unchanged are rather 
2019     /  for each font and style used there is an AFM file necessary. 
2020     /  currently i have only files for the roman font family. 
2021     /  I try to get files for the other ones! 
2023     /  CAVE: the size of the string is currently always calculated 
2024     /        in 'points' (1/72 of an inch). this should later on be 
2025     /        changed to depend on the mapping mode. 
2026     /  CAVE: the path to the AFM files must be set before calling this 
2027     /        function. this is usually done by a call like the following: 
2028     /        wxSetAFMPath("d:\\wxw161\\afm\\"); 
2032     /    wxPostScriptDC dc(NULL, TRUE); 
2034     /      wxSetAFMPath("d:\\wxw161\\afm\\"); 
2035     /      dc.StartDoc("Test"); 
2038     /      dc.SetFont(new wxFont(10, wxROMAN, wxNORMAL, wxNORMAL)); 
2039     /      dc.GetTextExtent("Hallo",&w,&h); 
2044     /  by steve (stefan.hammes@urz.uni-heidelberg.de) 
2046     /  updated: 14.05.95 */ 
2048     /* these static vars are for storing the state between calls */ 
2049     static int lastFamily
= INT_MIN
; 
2050     static int lastSize
= INT_MIN
; 
2051     static int lastStyle
= INT_MIN
; 
2052     static int lastWeight
= INT_MIN
; 
2053     static int lastDescender 
= INT_MIN
; 
2054     static int lastWidths
[256]; /* widths of the characters */ 
2056     double UnderlinePosition 
= 0.0; 
2057     double UnderlineThickness 
= 0.0; 
2059     /* get actual parameters */ 
2060     int Family 
= fontToUse
->GetFamily(); 
2061     int Size 
=   fontToUse
->GetPointSize(); 
2062     int Style 
=  fontToUse
->GetStyle(); 
2063     int Weight 
= fontToUse
->GetWeight(); 
2065     /* if we have another font, read the font-metrics */ 
2066     if (Family
!=lastFamily 
|| Size
!=lastSize 
|| Style
!=lastStyle 
|| Weight
!=lastWeight
) 
2068         /* store actual values */ 
2069         lastFamily 
= Family
; 
2072         lastWeight 
= Weight
; 
2074         const char *name 
= NULL
; 
2081                 if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "CourBoO.afm"; 
2082                 else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "CourBo.afm"; 
2083                 else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "CourO.afm"; 
2084                 else name 
= "Cour.afm"; 
2089                 if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "TimesBoO.afm"; 
2090                 else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "TimesBo.afm"; 
2091                 else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "TimesO.afm"; 
2092                 else name 
= "TimesRo.afm"; 
2104                 if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "HelvBoO.afm"; 
2105                 else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "HelvBo.afm"; 
2106                 else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "HelvO.afm"; 
2107                 else name 
= "Helv.afm"; 
2112         /* get the directory of the AFM files */ 
2113         wxString afmName 
= wxEmptyString
; 
2114         if (!m_printData
.GetFontMetricPath().IsEmpty()) 
2116             afmName 
= m_printData
.GetFontMetricPath(); 
2119         /* 2. open and process the file 
2120            /  a short explanation of the AFM format: 
2121            /  we have for each character a line, which gives its size 
2124            /    C 63 ; WX 444 ; N question ; B 49 -14 395 676 ; 
2126            /  that means, we have a character with ascii code 63, and width 
2127            /  (444/1000 * fontSize) points. 
2128            /  the other data is ignored for now! 
2130            /  when the font has changed, we read in the right AFM file and store the 
2131            /  character widths in an array, which is processed below (see point 3.). */ 
2133         /* new elements JC Sun Aug 25 23:21:44 MET DST 1996 */ 
2136         FILE *afmFile 
= wxFopen(afmName
,wxT("r")); 
2140            afmName 
= wxThePrintSetupData
->GetAFMPath(); 
2141            afmName 
<< wxFILE_SEP_PATH 
<< name
; 
2142            afmFile 
= wxFopen(afmName
,wxT("r")); 
2145 #if defined(__UNIX__) && !defined(__VMS__) 
2147         /* please do NOT change the line above to "else if (afmFile==NULL)" - 
2148            - afmFile = fopen() may fail and in that case the next if branch 
2149            MUST be executed - and it would not if there was "else" */ 
2151            afmName 
= wxGetDataDir(); 
2152            afmName 
<<  wxFILE_SEP_PATH
 
2153 #if defined(__LINUX__) || defined(__FREEBSD__) 
2154                    << wxT("gs_afm") << wxFILE_SEP_PATH
 
2156                    << wxT("afm") << wxFILE_SEP_PATH
 
2159            afmFile 
= wxFopen(afmName
,wxT("r")); 
2165             wxLogDebug( wxT("GetTextExtent: can't open AFM file '%s'"), afmName
.c_str() ); 
2166             wxLogDebug( wxT("               using approximate values")); 
2167             for (int i
=0; i
<256; i
++) lastWidths
[i
] = 500; /* an approximate value */ 
2168             lastDescender 
= -150; /* dito. */ 
2172             /* init the widths array */ 
2173             for(int i
=0; i
<256; i
++) lastWidths
[i
] = INT_MIN
; 
2174             /* some variables for holding parts of a line */ 
2175             char cString
[10],semiString
[10],WXString
[10],descString
[20]; 
2176             char upString
[30], utString
[30], encString
[50]; 
2179             /* read in the file and parse it */ 
2180             while(fgets(line
,sizeof(line
),afmFile
)!=NULL
) 
2182                 /* A.) check for descender definition */ 
2183                 if (strncmp(line
,"Descender",9)==0) 
2185                     if ((sscanf(line
,"%s%d",descString
,&lastDescender
)!=2) || 
2186                             (strcmp(descString
,"Descender")!=0)) 
2188                         wxLogDebug( wxT("AFM-file '%s': line '%s' has error (bad descender)"), afmName
.c_str(),line 
); 
2191                 /* JC 1.) check for UnderlinePosition */ 
2192                 else if(strncmp(line
,"UnderlinePosition",17)==0) 
2194                     if ((sscanf(line
,"%s%lf",upString
,&UnderlinePosition
)!=2) || 
2195                             (strcmp(upString
,"UnderlinePosition")!=0)) 
2197                         wxLogDebug( wxT("AFM-file '%s': line '%s' has error (bad UnderlinePosition)"), afmName
.c_str(), line 
); 
2200                 /* JC 2.) check for UnderlineThickness */ 
2201                 else if(strncmp(line
,"UnderlineThickness",18)==0) 
2203                     if ((sscanf(line
,"%s%lf",utString
,&UnderlineThickness
)!=2) || 
2204                             (strcmp(utString
,"UnderlineThickness")!=0)) 
2206                         wxLogDebug( wxT("AFM-file '%s': line '%s' has error (bad UnderlineThickness)"), afmName
.c_str(), line 
); 
2209                 /* JC 3.) check for EncodingScheme */ 
2210                 else if(strncmp(line
,"EncodingScheme",14)==0) 
2212                     if ((sscanf(line
,"%s%s",utString
,encString
)!=2) || 
2213                             (strcmp(utString
,"EncodingScheme")!=0)) 
2215                         wxLogDebug( wxT("AFM-file '%s': line '%s' has error (bad EncodingScheme)"), afmName
.c_str(), line 
); 
2217                     else if (strncmp(encString
, "AdobeStandardEncoding", 21)) 
2219                         wxLogDebug( wxT("AFM-file '%s': line '%s' has error (unsupported EncodingScheme %s)"), 
2220                                 afmName
.c_str(),line
, encString
); 
2223                 /* B.) check for char-width */ 
2224                 else if(strncmp(line
,"C ",2)==0) 
2226                     if (sscanf(line
,"%s%d%s%s%d",cString
,&ascii
,semiString
,WXString
,&cWidth
)!=5) 
2228                         wxLogDebug(wxT("AFM-file '%s': line '%s' has an error (bad character width)"),afmName
.c_str(),line
); 
2230                     if(strcmp(cString
,"C")!=0 || strcmp(semiString
,";")!=0 || strcmp(WXString
,"WX")!=0) 
2232                         wxLogDebug(wxT("AFM-file '%s': line '%s' has a format error"),afmName
.c_str(),line
); 
2234                     /* printf("            char '%c'=%d has width '%d'\n",ascii,ascii,cWidth); */ 
2235                     if (ascii
>=0 && ascii
<256) 
2237                         lastWidths
[ascii
] = cWidth
; /* store width */ 
2241                         /* MATTHEW: this happens a lot; don't print an error */ 
2242                         /* wxLogDebug("AFM-file '%s': ASCII value %d out of range",afmName.c_str(),ascii); */ 
2245                 /* C.) ignore other entries. */ 
2249         /* hack to compute correct values for german 'Umlaute' 
2250            /  the correct way would be to map the character names 
2251            /  like 'adieresis' to corresp. positions of ISOEnc and read 
2252            /  these values from AFM files, too. Maybe later ... */ 
2253         lastWidths
[196] = lastWidths
['A'];  // Ä 
2254         lastWidths
[228] = lastWidths
['a'];  // ä 
2255         lastWidths
[214] = lastWidths
['O'];  // Ö 
2256         lastWidths
[246] = lastWidths
['o'];  // ö 
2257         lastWidths
[220] = lastWidths
['U'];  // Ü 
2258         lastWidths
[252] = lastWidths
['u'];  // ü 
2259         lastWidths
[223] = lastWidths
[251];  // ß 
2261         /* JC: calculate UnderlineThickness/UnderlinePosition */ 
2263         // VS: dirty, but is there any better solution? 
2265         pt 
= (double*) &m_underlinePosition
; 
2266         *pt 
= LogicalToDeviceYRel((wxCoord
)(UnderlinePosition 
* fontToUse
->GetPointSize())) / 1000.0f
; 
2267         pt 
= (double*) &m_underlineThickness
; 
2268         *pt 
= LogicalToDeviceYRel((wxCoord
)(UnderlineThickness 
* fontToUse
->GetPointSize())) / 1000.0f
; 
2273     /* 3. now the font metrics are read in, calc size this 
2274        /  is done by adding the widths of the characters in the 
2275        /  string. they are given in 1/1000 of the size! */ 
2278     wxCoord height
=Size
; /* by default */ 
2280     for(p
=(unsigned char *)wxMBSTRINGCAST strbuf
; *p
; p
++) 
2282         if(lastWidths
[*p
]== INT_MIN
) 
2284             wxLogDebug(wxT("GetTextExtent: undefined width for character '%c' (%d)"), *p
,*p
); 
2285             sum 
+= lastWidths
[' ']; /* assume space */ 
2289             sum 
+= lastWidths
[*p
]; 
2293     double widthSum 
= sum
; 
2295     widthSum 
/= 1000.0F
; 
2297     /* add descender to height (it is usually a negative value) */ 
2298     //if (lastDescender != INT_MIN) 
2300     //    height += (wxCoord)(((-lastDescender)/1000.0F) * Size); /* MATTHEW: forgot scale */ 
2302     // - commented by V. Slavik - height already contains descender in it 
2303     //   (judging from few experiments) 
2305     /* return size values */ 
2307         *x 
= (wxCoord
)widthSum
; 
2311     /* return other parameters */ 
2314         if(lastDescender
!=INT_MIN
) 
2316             *descent 
= (wxCoord
)(((-lastDescender
)/1000.0F
) * Size
); /* MATTHEW: forgot scale */ 
2324     /* currently no idea how to calculate this! */ 
2325     if (externalLeading
) *externalLeading 
= 0; 
2330 // Determine the Default Postscript Previewer 
2331 // available on the platform 
2332 #if defined(__SUN__) && defined(__XVIEW__) 
2333 // OpenWindow/NeWS's Postscript Previewer 
2334 # define PS_VIEWER_PROG "pageview" 
2335 #elif defined(__VMS__) 
2336 #define PS_VIEWER_PROG "view/format=ps/select=x_display" 
2337 #elif defined(__SGI__) 
2338 // SGI's Display Postscript Previewer 
2339 //# define PS_VIEWER_PROG "dps" 
2340 # define PS_VIEWER_PROG "xpsview" 
2341 #elif defined(__X__) || defined(__WXGTK__) 
2342 // Front-end to ghostscript 
2343 # define PS_VIEWER_PROG "ghostview" 
2345 // Windows ghostscript/ghostview 
2346 # define PS_VIEWER_PROG "gsview" 
2349 wxPrintSetupData 
*wxThePrintSetupData 
= (wxPrintSetupData 
*) NULL
; 
2351 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptDC
, wxDC
) 
2352 IMPLEMENT_DYNAMIC_CLASS(wxPrintSetupData
, wxObject
) 
2354 // Redundant now I think 
2356 IMPLEMENT_CLASS(wxPostScriptPrintDialog
, wxDialog
) 
2358 wxPostScriptPrintDialog::wxPostScriptPrintDialog (wxWindow 
*parent
, const wxString
& title
, 
2359             const wxPoint
& pos
, const wxSize
& size
, wxCoord style
): 
2360    wxDialog(parent
, -1, title
, pos
, size
, style
) 
2362    wxBeginBusyCursor(); 
2367       *orientation 
= new wxString
[2], 
2368       *print_modes 
= new wxString
[3]; 
2370    wxCoord wx_printer_translate_x
, wx_printer_translate_y
; 
2371    double wx_printer_scale_x
, wx_printer_scale_y
; 
2373    orientation
[0] = _("Portrait"); 
2374    orientation
[1] = _("Landscape"); 
2376    print_modes
[0] = _("Send to Printer"); 
2377    print_modes
[1] = _("Print to File"); 
2378    print_modes
[2] = _("Preview Only"); 
2382    wxButton 
*okBut 
= new wxButton (this, wxID_OK
, _("OK"), wxPoint(5, 5)); 
2383    (void) new wxButton (this, wxID_CANCEL
, _("Cancel"), wxPoint(40, 5)); 
2384    okBut
->SetDefault(); 
2387 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
2388    (void) new wxStaticText( this, -1, _("Printer Command: "), 
2390    (void) new wxTextCtrl( this, wxID_PRINTER_COMMAND
, wxThePrintSetupData
->GetPrinterCommand(), 
2391                           wxPoint(100, yPos
), wxSize(100, -1) ); 
2393    (void) new wxStaticText( this, -1, _("Printer Options: "), 
2394                             wxPoint(210, yPos
) ); 
2395    (void) new wxTextCtrl( this, wxID_PRINTER_OPTIONS
, wxThePrintSetupData
->GetPrinterOptions(), 
2396                           wxPoint(305, yPos
), wxSize(150, -1) ); 
2402    wxRadioBox 
*radio0 
= new wxRadioBox(this, wxID_PRINTER_ORIENTATION
, "Orientation: ", wxPoint(5, yPos
), wxSize(-1,-1), 
2403                                        2,orientation
,2,wxRA_SPECIFY_ROWS
); 
2404    radio0
->SetSelection((int)wxThePrintSetupData
->GetPrinterOrientation() - 1); 
2406   // @@@ Configuration hook 
2407    if ( !wxThePrintSetupData
->GetPrintPreviewCommand() ) 
2408       wxThePrintSetupData
->SetPrintPreviewCommand(PS_VIEWER_PROG
); 
2410    //   wxGetResource ("wxWindows", "PSView", &wxThePrintSetupData->m_previewCommand); 
2412    features 
= (wxThePrintSetupData
->GetPrintPreviewCommand() && 
2413                *wxThePrintSetupData
->GetPrintPreviewCommand()) ? 3 : 2; 
2415    wxRadioBox 
*radio1 
= new wxRadioBox(this, wxID_PRINTER_MODES
, _("PostScript:"), 
2417                                        wxSize(-1,-1), features
, 
2418                                        print_modes
, features
, wxRA_SPECIFY_ROWS
); 
2421    radio1
->Enable(0, FALSE
); 
2422    if (wxThePrintSetupData
->GetPrintPreviewCommand() && *wxThePrintSetupData
->GetPrintPreviewCommand()) 
2423       radio1
->Enable(2, FALSE
); 
2426    radio1
->SetSelection((int)wxThePrintSetupData
->GetPrinterMode()); 
2427    wxThePrintSetupData
->GetPrinterTranslation(&wx_printer_translate_x
, &wx_printer_translate_y
); 
2428    wxThePrintSetupData
->GetPrinterScaling(&wx_printer_scale_x
, &wx_printer_scale_y
); 
2430    sprintf (buf
, "%.2f", wx_printer_scale_x
); 
2433    (void) new wxStaticText(this, -1, _("X Scaling"), wxPoint(5, yPos
)); 
2434    /* wxTextCtrl *text1 = */ (void) new wxTextCtrl(this, wxID_PRINTER_X_SCALE
, buf
, wxPoint(100, yPos
), wxSize(100, -1)); 
2436    sprintf (buf
, "%.2f", wx_printer_scale_y
); 
2437    (void) new wxStaticText(this, -1, _("Y Scaling"), wxPoint(220, yPos
)); 
2438    /* wxTextCtrl *text2 = */ (void) new wxTextCtrl(this, wxID_PRINTER_Y_SCALE
, buf
, wxPoint(320, yPos
), wxSize(100, -1)); 
2442    (void) new wxStaticText(this, -1, _("X Translation"), wxPoint(5, yPos
)); 
2443    sprintf (buf
, "%.2d", wx_printer_translate_x
); 
2444    /* wxTextCtrl *text3 = */ (void) new wxTextCtrl(this, wxID_PRINTER_X_TRANS
, buf
, wxPoint(100, yPos
), wxSize(100, -1)); 
2446    (void) new wxStaticText(this, -1, _("Y Translation"), wxPoint(220, yPos
)); 
2447    sprintf (buf
, "%.2d", wx_printer_translate_y
); 
2448    /* wxTextCtrl *text4 = */ (void) new wxTextCtrl(this, wxID_PRINTER_Y_TRANS
, buf
, wxPoint(320, yPos
), wxSize(100, -1)); 
2452    delete[] orientation
; 
2453    delete[] print_modes
; 
2458 int wxPostScriptPrintDialog::ShowModal () 
2460   if ( wxDialog::ShowModal() == wxID_OK 
) 
2462 //    wxTextCtrl *text0 = (wxTextCtrl *)FindWindow(wxID_PRINTER_OPTIONS); 
2463       wxTextCtrl 
*text1 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_X_SCALE
); 
2464       wxTextCtrl 
*text2 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_Y_SCALE
); 
2465       wxTextCtrl 
*text3 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_X_TRANS
); 
2466       wxTextCtrl 
*text4 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_Y_TRANS
); 
2467 //    wxTextCtrl *text_prt = (wxTextCtrl *)FindWindow(wxID_PRINTER_COMMAND); 
2468       wxRadioBox 
*radio0 
= (wxRadioBox 
*)FindWindow(wxID_PRINTER_ORIENTATION
); 
2469       wxRadioBox 
*radio1 
= (wxRadioBox 
*)FindWindow(wxID_PRINTER_MODES
); 
2471       StringToDouble (WXSTRINGCAST text1
->GetValue (), &wxThePrintSetupData
->m_printerScaleX
); 
2472       StringToDouble (WXSTRINGCAST text2
->GetValue (), &wxThePrintSetupData
->m_printerScaleY
); 
2475       StringToLong (WXSTRINGCAST text3
->GetValue (), &dummy
); 
2476       wxThePrintSetupData
->m_printerTranslateX 
= (wxCoord
)dummy
; 
2477       StringToLong (WXSTRINGCAST text4
->GetValue (), &dummy
); 
2478       wxThePrintSetupData
->m_printerTranslateY 
= (wxCoord
)dummy
; 
2481       //      wxThePrintSetupData->SetPrinterOptions(WXSTRINGCAST text0->GetValue ()); 
2482       //      wxThePrintSetupData->SetPrinterCommand(WXSTRINGCAST text_prt->GetValue ()); 
2485       wxThePrintSetupData
->SetPrinterOrientation((radio0
->GetSelection() == 1 ? wxLANDSCAPE 
: wxPORTRAIT
)); 
2488       switch ( radio1
->GetSelection() ) { 
2489         case 0: wxThePrintSetupData
->SetPrinterMode(PS_PRINTER
); break; 
2490         case 1:  wxThePrintSetupData
->SetPrinterMode(PS_FILE
); break; 
2491         case 2: wxThePrintSetupData
->SetPrinterMode(PS_PREVIEW
); break; 
2500 // PostScript printer settings 
2501 // RETAINED FOR BACKWARD COMPATIBILITY 
2502 void wxSetPrinterCommand(const wxString
& cmd
) 
2504   wxThePrintSetupData
->SetPrinterCommand(cmd
); 
2507 void wxSetPrintPreviewCommand(const wxString
& cmd
) 
2509   wxThePrintSetupData
->SetPrintPreviewCommand(cmd
); 
2512 void wxSetPrinterOptions(const wxString
& flags
) 
2514   wxThePrintSetupData
->SetPrinterOptions(flags
); 
2517 void wxSetPrinterFile(const wxString
& f
) 
2519   wxThePrintSetupData
->SetPrinterFile(f
); 
2522 void wxSetPrinterOrientation(int orient
) 
2524   wxThePrintSetupData
->SetPrinterOrientation(orient
); 
2527 void wxSetPrinterScaling(double x
, double y
) 
2529   wxThePrintSetupData
->SetPrinterScaling(x
, y
); 
2532 void wxSetPrinterTranslation(wxCoord x
, wxCoord y
) 
2534   wxThePrintSetupData
->SetPrinterTranslation(x
, y
); 
2537 // 1 = Preview, 2 = print to file, 3 = send to printer 
2538 void wxSetPrinterMode(int mode
) 
2540   wxThePrintSetupData
->SetPrinterMode(mode
); 
2543 void wxSetAFMPath(const wxString
& f
) 
2545   wxThePrintSetupData
->SetAFMPath(f
); 
2548 // Get current values 
2549 wxString 
wxGetPrinterCommand() 
2551   return wxThePrintSetupData
->GetPrinterCommand(); 
2554 wxString 
wxGetPrintPreviewCommand() 
2556   return wxThePrintSetupData
->GetPrintPreviewCommand(); 
2559 wxString 
wxGetPrinterOptions() 
2561   return wxThePrintSetupData
->GetPrinterOptions(); 
2564 wxString 
wxGetPrinterFile() 
2566   return wxThePrintSetupData
->GetPrinterFile(); 
2569 int wxGetPrinterOrientation() 
2571   return wxThePrintSetupData
->GetPrinterOrientation(); 
2574 void wxGetPrinterScaling(double* x
, double* y
) 
2576   wxThePrintSetupData
->GetPrinterScaling(x
, y
); 
2579 void wxGetPrinterTranslation(wxCoord 
*x
, wxCoord 
*y
) 
2581   wxThePrintSetupData
->GetPrinterTranslation(x
, y
); 
2584 int wxGetPrinterMode() 
2586   return wxThePrintSetupData
->GetPrinterMode(); 
2589 wxString 
wxGetAFMPath() 
2591   return wxThePrintSetupData
->GetAFMPath(); 
2598 wxPrintSetupData::wxPrintSetupData() 
2600   m_printerOrient 
= wxPORTRAIT
; 
2601   m_printerScaleX 
= (double)1.0; 
2602   m_printerScaleY 
= (double)1.0; 
2603   m_printerTranslateX 
= 0; 
2604   m_printerTranslateY 
= 0; 
2605   m_printerMode 
= wxPRINT_MODE_FILE
; 
2606   m_printColour 
= TRUE
; 
2609 wxPrintSetupData::~wxPrintSetupData() 
2613 void wxPrintSetupData::operator=(wxPrintSetupData
& data
) 
2615   SetPrinterCommand(data
.GetPrinterCommand()); 
2616   SetPrintPreviewCommand(data
.GetPrintPreviewCommand()); 
2617   SetPrinterOptions(data
.GetPrinterOptions()); 
2619   data
.GetPrinterTranslation(&x
, &y
); 
2620   SetPrinterTranslation(x
, y
); 
2623   data
.GetPrinterScaling(&x1
, &y1
); 
2624   SetPrinterScaling(x1
, y1
); 
2626   SetPrinterOrientation(data
.GetPrinterOrientation()); 
2627   SetPrinterMode(data
.GetPrinterMode()); 
2628   SetAFMPath(data
.GetAFMPath()); 
2629   SetPaperName(data
.GetPaperName()); 
2630   SetColour(data
.GetColour()); 
2633 // Initialize from a wxPrintData object (wxPrintData should now be used instead of wxPrintSetupData). 
2634 void wxPrintSetupData::operator=(const wxPrintData
& data
) 
2636     SetPrinterCommand(data
.GetPrinterCommand()); 
2637     SetPrintPreviewCommand(data
.GetPreviewCommand()); 
2638     SetPrinterOptions(data
.GetPrinterOptions()); 
2639     SetPrinterTranslation((wxCoord
)data
.GetPrinterTranslateX(), 
2640                           (wxCoord
)data
.GetPrinterTranslateY()); 
2641     SetPrinterScaling(data
.GetPrinterScaleX(), data
.GetPrinterScaleY()); 
2642     SetPrinterOrientation(data
.GetOrientation()); 
2643     SetPrinterMode((int) data
.GetPrintMode()); 
2644     SetAFMPath(data
.GetFontMetricPath()); 
2645     SetPaperName(wxThePrintPaperDatabase
->ConvertIdToName(data
.GetPaperId())); 
2646     SetColour(data
.GetColour()); 
2647     SetPrinterFile(data
.GetFilename()); 
2650 void wxInitializePrintSetupData(bool init
) 
2654     wxThePrintSetupData 
= new wxPrintSetupData
; 
2656     wxThePrintSetupData
->SetPrintPreviewCommand(PS_VIEWER_PROG
); 
2657     wxThePrintSetupData
->SetPrinterOrientation(wxPORTRAIT
); 
2658     wxThePrintSetupData
->SetPrinterMode(wxPRINT_MODE_PREVIEW
); 
2659     wxThePrintSetupData
->SetPaperName(_("A4 sheet, 210 x 297 mm")); 
2661     // Could have a .ini file to read in some defaults 
2662     // - and/or use environment variables, e.g. WXWIN 
2664     wxThePrintSetupData
->SetPrinterCommand("print"); 
2665     wxThePrintSetupData
->SetPrinterOptions("/nonotify/queue=psqueue"); 
2666     wxThePrintSetupData
->SetAFMPath("sys$ps_font_metrics:"); 
2669     wxThePrintSetupData
->SetPrinterCommand("print"); 
2670     wxThePrintSetupData
->SetAFMPath("c:\\windows\\system\\"); 
2671     wxThePrintSetupData
->SetPrinterOptions(""); 
2673 #if !defined(__VMS__) && !defined(__WXMSW__) 
2674     wxThePrintSetupData
->SetPrinterCommand("lpr"); 
2675     wxThePrintSetupData
->SetPrinterOptions(""); 
2676     wxThePrintSetupData
->SetAFMPath(""); 
2681     if (wxThePrintSetupData
) 
2682       delete wxThePrintSetupData
; 
2683      wxThePrintSetupData 
= (wxPrintSetupData 
*) NULL
; 
2687 // A module to allow initialization/cleanup of PostScript-related 
2688 // things without calling these functions from app.cpp. 
2690 class WXDLLEXPORT wxPostScriptModule
: public wxModule
 
2692 DECLARE_DYNAMIC_CLASS(wxPostScriptModule
) 
2694     wxPostScriptModule() {} 
2699 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptModule
, wxModule
) 
2702  * Initialization/cleanup module 
2705 bool wxPostScriptModule::OnInit() 
2707     wxInitializePrintSetupData(); 
2712 void wxPostScriptModule::OnExit() 
2714     wxInitializePrintSetupData(FALSE
); 
2721   // wxUSE_PRINTING_ARCHITECTURE