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" 
  49 #include "wx/filefn.h" 
  73 //----------------------------------------------------------------------------- 
  74 // start and end of document/page 
  75 //----------------------------------------------------------------------------- 
  77 static const char *wxPostScriptHeaderEllipse 
= "\ 
  78 /ellipsedict 8 dict def\n\ 
  79 ellipsedict /mtrx matrix put\n\ 
  83     /startangle exch def\n\ 
  88     /savematrix mtrx currentmatrix def\n\ 
  91     0 0 1 startangle endangle arc\n\ 
  92     savematrix setmatrix\n\ 
  97 static const char *wxPostScriptHeaderEllipticArc
= "\ 
  98 /ellipticarcdict 8 dict def\n\ 
  99 ellipticarcdict /mtrx matrix put\n\ 
 101 { ellipticarcdict begin\n\ 
 103   /endangle exch def\n\ 
 104   /startangle exch def\n\ 
 109   /savematrix mtrx currentmatrix def\n\ 
 112   do_fill { 0 0 moveto } if\n\ 
 113   0 0 1 startangle endangle arc\n\ 
 114   savematrix setmatrix\n\ 
 115   do_fill { fill }{ stroke } ifelse\n\ 
 119 static const char *wxPostScriptHeaderSpline 
= "\ 
 120 /DrawSplineSection {\n\ 
 127     /xa x1 x2 x1 sub 0.666667 mul add def\n\ 
 128     /ya y1 y2 y1 sub 0.666667 mul add def\n\ 
 129     /xb x3 x2 x3 sub 0.666667 mul add def\n\ 
 130     /yb y3 y2 y3 sub 0.666667 mul add def\n\ 
 132     xa ya xb yb x3 y3 curveto\n\ 
 136 static const char *wxPostScriptHeaderColourImage 
= "\ 
 137 %% define 'colorimage' if it isn't defined\n\ 
 138 %%   ('colortogray' and 'mergeprocs' come from xwd2ps\n\ 
 140 /colorimage where   %% do we know about 'colorimage'?\n\ 
 141   { pop }           %% yes: pop off the 'dict' returned\n\ 
 142   {                 %% no:  define one\n\ 
 143     /colortogray {  %% define an RGB->I function\n\ 
 144       /rgbdata exch store    %% call input 'rgbdata'\n\ 
 145       rgbdata length 3 idiv\n\ 
 146       /npixls exch store\n\ 
 148       0 1 npixls 1 sub {\n\ 
 150         rgbdata rgbindx       get 20 mul    %% Red\n\ 
 151         rgbdata rgbindx 1 add get 32 mul    %% Green\n\ 
 152         rgbdata rgbindx 2 add get 12 mul    %% Blue\n\ 
 153         add add 64 idiv      %% I = .5G + .31R + .18B\n\ 
 155         /rgbindx rgbindx 3 add store\n\ 
 157       grays 0 npixls getinterval\n\ 
 160     %% Utility procedure for colorimage operator.\n\ 
 161     %% This procedure takes two procedures off the\n\ 
 162     %% stack and merges them into a single procedure.\n\ 
 164     /mergeprocs { %% def\n\ 
 183     /colorimage { %% def\n\ 
 184       pop pop     %% remove 'false 3' operands\n\ 
 185       {colortogray} mergeprocs\n\ 
 188   } ifelse          %% end of 'false' case\n\ 
 191 static char wxPostScriptHeaderReencodeISO1
[] = 
 193 "dup dup findfont dup length dict begin\n" 
 194 "{ 1 index /FID ne { def }{ pop pop } ifelse } forall\n" 
 195 "/Encoding ISOLatin1Encoding def\n" 
 196 "currentdict end definefont\n" 
 198 "/ISOLatin1Encoding [\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 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 203 "/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright\n" 
 204 "/parenleft/parenright/asterisk/plus/comma/minus/period/slash\n" 
 205 "/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon\n" 
 206 "/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N\n" 
 207 "/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright\n" 
 208 "/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m\n" 
 209 "/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde\n" 
 210 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 211 "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef\n" 
 212 "/.notdef/dotlessi/grave/acute/circumflex/tilde/macron/breve\n" 
 213 "/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut\n"; 
 215 static char wxPostScriptHeaderReencodeISO2
[] = 
 216 "/ogonek/caron/space/exclamdown/cent/sterling/currency/yen/brokenbar\n" 
 217 "/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot\n" 
 218 "/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior\n" 
 219 "/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine\n" 
 220 "/guillemotright/onequarter/onehalf/threequarters/questiondown\n" 
 221 "/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla\n" 
 222 "/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex\n" 
 223 "/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis\n" 
 224 "/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute\n" 
 225 "/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis\n" 
 226 "/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave\n" 
 227 "/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex\n" 
 228 "/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis\n" 
 229 "/yacute/thorn/ydieresis\n" 
 232 //------------------------------------------------------------------------------- 
 234 //------------------------------------------------------------------------------- 
 236 wxPostScriptDC::wxPostScriptDC () 
 238     m_pstream 
= (FILE*) NULL
; 
 248     m_underlinePosition 
= 0.0; 
 249     m_underlineThickness 
= 0.0; 
 251     m_signX 
=  1;  // default x-axis left to right 
 252     m_signY 
= -1;  // default y-axis bottom up -> top down 
 254     // Compatibility only 
 255     // HH: Doesn't seem to work for wxMSW... 
 257     m_printData 
= * wxThePrintSetupData
; 
 261 wxPostScriptDC::wxPostScriptDC (const wxString
& file
, bool interactive
, wxWindow 
*parent
) 
 263     m_pstream 
= (FILE*) NULL
; 
 273     m_underlinePosition 
= 0.0; 
 274     m_underlineThickness 
= 0.0; 
 276     m_signX 
=  1;  // default x-axis left to right 
 277     m_signY 
= -1;  // default y-axis bottom up -> top down 
 279     Create(file
, interactive
, parent
); 
 282 bool wxPostScriptDC::Create(const wxString
& file
, bool interactive
, wxWindow 
*parent
) 
 284     m_isInteractive 
= interactive
; 
 287     m_printData
.SetFilename(file
); 
 290     // Can only send to file in Windows 
 291     m_printData
.SetPrintMode(wxPRINT_MODE_FILE
); 
 296         if ((m_ok 
= PrinterDialog (parent
) ) == FALSE
) return FALSE
; 
 306 wxPostScriptDC::wxPostScriptDC (const wxPrintData
& printData
) 
 308     m_pstream 
= (FILE*) NULL
; 
 318     m_underlinePosition 
= 0.0; 
 319     m_underlineThickness 
= 0.0; 
 321     m_signX 
=  1;  // default x-axis left to right 
 322     m_signY 
= -1;  // default y-axis bottom up -> top down 
 324     m_printData 
= printData
; 
 329 wxPostScriptDC::~wxPostScriptDC () 
 334         m_pstream 
= (FILE*) NULL
; 
 338 bool wxPostScriptDC::Ok() const 
 343 // This dialog is deprecated now: use wxGenericPrintDialog or the printing framework 
 344 bool wxPostScriptDC::PrinterDialog(wxWindow 
*parent
) 
 346     wxPostScriptPrintDialog 
dialog( parent
, _("Printer Settings"), wxPoint(150, 150), wxSize(400, 400), 
 347                                     wxDEFAULT_DIALOG_STYLE 
| wxDIALOG_MODAL 
); 
 348     m_ok 
= (dialog
.ShowModal () == wxID_OK
); 
 350     if (!m_ok
) return FALSE
; 
 352     if ((m_printData
.GetFilename() == "") && 
 353         (m_printData
.GetPrintMode() == wxPRINT_MODE_PREVIEW  
|| 
 354          m_printData
.GetPrintMode() == wxPRINT_MODE_PRINTER
)) 
 358       m_printData
.SetFilename("preview"); 
 360       // For PS_PRINTER action this depends on a Unix-style print spooler 
 361       // since the wx_printer_file can be destroyed during a session 
 362       // @@@ TODO: a Windows-style answer for non-Unix 
 364       wxGetUserId (userId
, sizeof (userId
) / sizeof (char)); 
 366       wxStrcpy (tmp
, wxT("/tmp/preview_")); 
 367       wxStrcat (tmp
, userId
); 
 368       m_printData
.SetFilename(tmp
); 
 371       wxStrcpy(tmp2
, m_printData
.GetFilename()); 
 372       wxStrcat (tmp2
, wxT(".ps")); 
 373       m_printData
.SetFilename(tmp2
); 
 375     else if ((m_printData
.GetFilename() == wxT("")) && (m_printData
.GetPrintMode() == wxPRINT_MODE_FILE
)) 
 377       wxString file 
= wxSaveFileSelector (_("PostScript"), wxT("ps")); 
 378       if ( file
.IsEmpty() ) 
 384       m_printData
.SetFilename(file
); 
 391 void wxPostScriptDC::DoSetClippingRegion (wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
 393     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 395     if (m_clipping
) DestroyClippingRegion(); 
 397     wxDC::DoSetClippingRegion(x
, y
, w
, h
); 
 406             "closepath clip newpath\n", 
 407             XLOG2DEV(x
),   YLOG2DEV(y
), 
 408             XLOG2DEV(x
+w
), YLOG2DEV(y
), 
 409             XLOG2DEV(x
+w
), YLOG2DEV(y
+h
), 
 410             XLOG2DEV(x
),   YLOG2DEV(y
+h
) ); 
 414 void wxPostScriptDC::DestroyClippingRegion() 
 416     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 421         fprintf( m_pstream
, "grestore\n" ); 
 424     wxDC::DestroyClippingRegion(); 
 427 void wxPostScriptDC::Clear() 
 429     wxFAIL_MSG( wxT("wxPostScriptDC::Clear not implemented.") ); 
 432 void wxPostScriptDC::DoFloodFill (wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
), const wxColour 
&WXUNUSED(col
), int WXUNUSED(style
)) 
 434     wxFAIL_MSG( wxT("wxPostScriptDC::FloodFill not implemented.") ); 
 437 bool wxPostScriptDC::DoGetPixel (wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
), wxColour 
* WXUNUSED(col
)) const 
 439     wxFAIL_MSG( wxT("wxPostScriptDC::GetPixel not implemented.") ); 
 443 void wxPostScriptDC::DoCrossHair (wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
)) 
 445     wxFAIL_MSG( wxT("wxPostScriptDC::CrossHair not implemented.") ); 
 448 void wxPostScriptDC::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
) 
 450     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 452     if  (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 461             XLOG2DEV(x1
), YLOG2DEV(y1
), 
 462             XLOG2DEV(x2
), YLOG2DEV (y2
) ); 
 464     CalcBoundingBox( x1
, y1 
); 
 465     CalcBoundingBox( x2
, y2 
); 
 468 #define RAD2DEG 57.29577951308 
 470 void wxPostScriptDC::DoDrawArc (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
) 
 472     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 474     wxCoord dx 
= x1 
- xc
; 
 475     wxCoord dy 
= y1 
- yc
; 
 476     wxCoord radius 
= (wxCoord
) sqrt( (double)(dx
*dx
+dy
*dy
) ); 
 477     double alpha1
, alpha2
; 
 479     if (x1 
== x2 
&& y1 
== y2
) 
 484     else if (radius 
== 0.0) 
 486         alpha1 
= alpha2 
= 0.0; 
 490         alpha1 
= (x1 
- xc 
== 0) ? 
 491             (y1 
- yc 
< 0) ? 90.0 : -90.0 : 
 492                 -atan2(double(y1
-yc
), double(x1
-xc
)) * RAD2DEG
; 
 493         alpha2 
= (x2 
- xc 
== 0) ? 
 494             (y2 
- yc 
< 0) ? 90.0 : -90.0 : 
 495                 -atan2(double(y2
-yc
), double(x2
-xc
)) * RAD2DEG
; 
 497     while (alpha1 
<= 0)   alpha1 
+= 360; 
 498     while (alpha2 
<= 0)   alpha2 
+= 360; // adjust angles to be between 
 499     while (alpha1 
> 360)  alpha1 
-= 360; // 0 and 360 degree 
 500     while (alpha2 
> 360)  alpha2 
-= 360; 
 502     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 508                 "%d %d %d %d %d %d ellipse\n" 
 512                 XLOG2DEV(xc
), YLOG2DEV(yc
), XLOG2DEVREL(radius
), YLOG2DEVREL(radius
), (wxCoord
)alpha1
, (wxCoord
) alpha2
, 
 513                 XLOG2DEV(xc
), YLOG2DEV(yc
) ); 
 515         CalcBoundingBox( xc
-radius
, yc
-radius 
); 
 516         CalcBoundingBox( xc
+radius
, yc
+radius 
); 
 519     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 525                 "%d %d %d %d %d %d ellipse\n" 
 529                 XLOG2DEV(xc
), YLOG2DEV(yc
), XLOG2DEVREL(radius
), YLOG2DEVREL(radius
), (wxCoord
)alpha1
, (wxCoord
) alpha2
, 
 530                 XLOG2DEV(xc
), YLOG2DEV(yc
) ); 
 532         CalcBoundingBox( xc
-radius
, yc
-radius 
); 
 533         CalcBoundingBox( xc
+radius
, yc
+radius 
); 
 537 void wxPostScriptDC::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
) 
 539     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 541     if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360; 
 542     if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360; 
 548         DrawEllipse(x
,y
,w
,h
); 
 552     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 558                 "%d %d %d %d %d %d true ellipticarc\n", 
 559                 XLOG2DEV(x
+w
/2), YLOG2DEV(y
+h
/2), XLOG2DEVREL(w
/2), YLOG2DEVREL(h
/2), (wxCoord
)sa
, (wxCoord
)ea 
); 
 561         CalcBoundingBox( x 
,y 
); 
 562         CalcBoundingBox( x
+w
, y
+h 
); 
 565     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 571                 "%d %d %d %d %d %d false ellipticarc\n", 
 572                 XLOG2DEV(x
+w
/2), YLOG2DEV(y
+h
/2), XLOG2DEVREL(w
/2), YLOG2DEVREL(h
/2), (wxCoord
)sa
, (wxCoord
)ea 
); 
 574         CalcBoundingBox( x 
,y 
); 
 575         CalcBoundingBox( x
+w
, y
+h 
); 
 579 void wxPostScriptDC::DoDrawPoint (wxCoord x
, wxCoord y
) 
 581     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 583     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 592             XLOG2DEV(x
),   YLOG2DEV(y
), 
 593             XLOG2DEV(x
+1), YLOG2DEV(y
) ); 
 595     CalcBoundingBox( x
, y 
); 
 598 void wxPostScriptDC::DoDrawPolygon (int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
)) 
 600     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 604     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 608         fprintf( m_pstream
, "newpath\n" ); 
 610         wxCoord xx 
= XLOG2DEV(points
[0].x 
+ xoffset
); 
 611         wxCoord yy 
= YLOG2DEV(points
[0].y 
+ yoffset
); 
 613         fprintf( m_pstream
, "%d %d moveto\n", xx
, yy 
); 
 615         CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 617         for (int i 
= 1; i 
< n
; i
++) 
 619             xx 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 620             yy 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 622             fprintf( m_pstream
, "%d %d lineto\n", xx
, yy 
); 
 624             CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 627         fprintf( m_pstream
, "fill\n" ); 
 630     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 634         fprintf( m_pstream
, "newpath\n" ); 
 636         wxCoord xx 
= XLOG2DEV(points
[0].x 
+ xoffset
); 
 637         wxCoord yy 
= YLOG2DEV(points
[0].y 
+ yoffset
); 
 639         fprintf( m_pstream
, "%d %d moveto\n", xx
, yy 
); 
 641         CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 643         for (int i 
= 1; i 
< n
; i
++) 
 645             xx 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 646             yy 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 648             fprintf( m_pstream
, "%d %d lineto\n", xx
, yy 
); 
 650             CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 653         fprintf( m_pstream
, "fill\n" ); 
 657 void wxPostScriptDC::DoDrawLines (int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
) 
 659     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 661     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 668     for ( i 
=0; i
<n 
; i
++ ) 
 670         CalcBoundingBox( XLOG2DEV(points
[i
].x
+xoffset
), YLOG2DEV(points
[i
].y
+yoffset
)); 
 676             XLOG2DEV(points
[0].x
+xoffset
), YLOG2DEV(points
[0].y
+yoffset
) ); 
 678     for (i 
= 1; i 
< n
; i
++) 
 682                 XLOG2DEV(points
[i
].x
+xoffset
), YLOG2DEV(points
[i
].y
+yoffset
) ); 
 685     fprintf( m_pstream
, "stroke\n" ); 
 688 void wxPostScriptDC::DoDrawRectangle (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 690     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 692     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 704                 XLOG2DEV(x
),         YLOG2DEV(y
), 
 705                 XLOG2DEV(x 
+ width
), YLOG2DEV(y
), 
 706                 XLOG2DEV(x 
+ width
), YLOG2DEV(y 
+ height
), 
 707                 XLOG2DEV(x
),         YLOG2DEV(y 
+ height
) ); 
 709         CalcBoundingBox( x
, y 
); 
 710         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 713     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 725                 XLOG2DEV(x
),         YLOG2DEV(y
), 
 726                 XLOG2DEV(x 
+ width
), YLOG2DEV(y
), 
 727                 XLOG2DEV(x 
+ width
), YLOG2DEV(y 
+ height
), 
 728                 XLOG2DEV(x
),         YLOG2DEV(y 
+ height
) ); 
 730         CalcBoundingBox( x
, y 
); 
 731         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 735 void wxPostScriptDC::DoDrawRoundedRectangle (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
) 
 737     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 741         // Now, a negative radius is interpreted to mean 
 742         // 'the proportion of the smallest X or Y dimension' 
 743         double smallest 
= 0.0; 
 748         radius 
=  (-radius 
* smallest
); 
 751     wxCoord rad 
= (wxCoord
) radius
; 
 753     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 757         /* Draw rectangle anticlockwise */ 
 760                 "%d %d %d 90 180 arc\n" 
 762                 "%d %d %d 180 270 arc\n" 
 764                 "%d %d %d 270 0 arc\n" 
 766                 "%d %d %d 0 90 arc\n" 
 770                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y 
+ rad
), XLOG2DEVREL(rad
), 
 771                 XLOG2DEV(x
), YLOG2DEV(y 
+ rad
), 
 772                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y 
+ height 
- rad
), XLOG2DEVREL(rad
), 
 773                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ height
), 
 774                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ height 
- rad
), XLOG2DEVREL(rad
), 
 775                 XLOG2DEV(x 
+ width
), YLOG2DEV(y 
+ rad
), 
 776                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ rad
), XLOG2DEVREL(rad
), 
 777                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y
) ); 
 779         CalcBoundingBox( x
, y 
); 
 780         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 783     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 787         /* Draw rectangle anticlockwise */ 
 790                 "%d %d %d 90 180 arc\n" 
 792                 "%d %d %d 180 270 arc\n" 
 794                 "%d %d %d 270 0 arc\n" 
 796                 "%d %d %d 0 90 arc\n" 
 800                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y 
+ rad
), XLOG2DEVREL(rad
), 
 801                 XLOG2DEV(x
), YLOG2DEV(y 
+ rad
), 
 802                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y 
+ height 
- rad
), XLOG2DEVREL(rad
), 
 803                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ height
), 
 804                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ height 
- rad
), XLOG2DEVREL(rad
), 
 805                 XLOG2DEV(x 
+ width
), YLOG2DEV(y 
+ rad
), 
 806                 XLOG2DEV(x 
+ width 
- rad
), YLOG2DEV(y 
+ rad
), XLOG2DEVREL(rad
), 
 807                 XLOG2DEV(x 
+ rad
), YLOG2DEV(y
) ); 
 809         CalcBoundingBox( x
, y 
); 
 810         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 814 void wxPostScriptDC::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 816     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 818     if (m_brush
.GetStyle () != wxTRANSPARENT
) 
 824                 "%d %d %d %d 0 360 ellipse\n" 
 826                 XLOG2DEV(x 
+ width 
/ 2), YLOG2DEV(y 
+ height 
/ 2), 
 827                 XLOG2DEV(width 
/ 2), YLOG2DEVREL(height 
/ 2) ); 
 829         CalcBoundingBox( x 
- width
, y 
- height 
); 
 830         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 833     if (m_pen
.GetStyle () != wxTRANSPARENT
) 
 839                 "%d %d %d %d 0 360 ellipse\n" 
 841                 XLOG2DEV(x 
+ width 
/ 2), YLOG2DEV(y 
+ height 
/ 2), 
 842                 XLOG2DEV(width 
/ 2), YLOG2DEVREL(height 
/ 2) ); 
 844         CalcBoundingBox( x 
- width
, y 
- height 
); 
 845         CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 849 void wxPostScriptDC::DoDrawIcon( const wxIcon
& icon
, wxCoord x
, wxCoord y 
) 
 851     DrawBitmap( icon
, x
, y
, TRUE 
); 
 854 /* this has to be char, not wxChar */ 
 855 static char hexArray
[] = "0123456789ABCDEF"; 
 856 static void LocalDecToHex( int dec
, char *buf 
) 
 858     int firstDigit 
= (int)(dec
/16.0); 
 859     int secondDigit 
= (int)(dec 
- (firstDigit
*16.0)); 
 860     buf
[0] = hexArray
[firstDigit
]; 
 861     buf
[1] = hexArray
[secondDigit
]; 
 865 void wxPostScriptDC::DoDrawBitmap( const wxBitmap
& bitmap
, wxCoord x
, wxCoord y
, bool WXUNUSED(useMask
) ) 
 867     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 869     if (!bitmap
.Ok()) return; 
 871     wxImage 
image( bitmap 
); 
 873     if (!image
.Ok()) return; 
 875     wxCoord ww 
= XLOG2DEVREL(image
.GetWidth()); 
 876     wxCoord hh 
= YLOG2DEVREL(image
.GetHeight()); 
 878     image 
= image
.Scale( ww
, hh 
); 
 880     if (!image
.Ok()) return; 
 882     wxCoord xx 
= XLOG2DEV(x
); 
 883     wxCoord yy 
= YLOG2DEV(y 
+ bitmap
.GetHeight()); 
 886             "/origstate save def\n" 
 888             "/pix %d string def\n" 
 889             "/grays %d string def\n" 
 896             "{currentfile pix readhexstring pop}\n" 
 897             "false 3 colorimage\n", 
 898             ww
, ww
, xx
, yy
, ww
, hh
, ww
, hh
, ww
, -hh
, hh 
); 
 900     for (int j 
= 0; j 
< hh
; j
++) 
 902         for (int i 
= 0; i 
< ww
; i
++) 
 905             LocalDecToHex( image
.GetRed(i
,j
), buffer 
); 
 906             fprintf( m_pstream
, buffer 
); 
 907             LocalDecToHex( image
.GetGreen(i
,j
), buffer 
); 
 908             fprintf( m_pstream
, buffer 
); 
 909             LocalDecToHex( image
.GetBlue(i
,j
), buffer 
); 
 910             fprintf( m_pstream
, buffer 
); 
 912         fprintf( m_pstream
, "\n" ); 
 915     fprintf( m_pstream
, "end\n" ); 
 916     fprintf( m_pstream
, "origstate restore\n" ); 
 919 void wxPostScriptDC::SetFont( const wxFont
& font 
) 
 921     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
 923     if (!font
.Ok())  return; 
 928     const char *style 
= ""; 
 929     int Style 
= m_font
.GetStyle(); 
 930     int Weight 
= m_font
.GetWeight(); 
 932     switch (m_font
.GetFamily()) 
 942 //          name = "/Times-Roman"; 
 943             name 
= "/Times"; // Altered by EDZ 
 946             name 
= "/Zapf-Chancery-MediumItalic"; 
 951         case wxDEFAULT
: // Sans Serif Font 
 952             name 
= "/LucidaSans"; 
 955     if (Style 
== wxNORMAL 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 957         if (m_font
.GetFamily () == wxROMAN
) 
 962     else if (Style 
== wxNORMAL 
&& Weight 
== wxBOLD
) 
 966     else if (Style 
== wxITALIC 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 968         if (m_font
.GetFamily () == wxROMAN
) 
 973     else if (Style 
== wxITALIC 
&& Weight 
== wxBOLD
) 
 975         if (m_font
.GetFamily () == wxROMAN
) 
 976             style 
= "-BoldItalic"; 
 978             style 
= "-BoldOblique"; 
 980     else if (Style 
== wxSLANT 
&& (Weight 
== wxNORMAL 
|| Weight 
== wxLIGHT
)) 
 982         if (m_font
.GetFamily () == wxROMAN
) 
 987     else if (Style 
== wxSLANT 
&& Weight 
== wxBOLD
) 
 989         if (m_font
.GetFamily () == wxROMAN
) 
 990             style 
= "-BoldItalic"; 
 992             style 
= "-BoldOblique"; 
1000     strcpy( buffer
, name 
); 
1001     strcat( buffer
, style 
); 
1003     fprintf( m_pstream
, buffer 
); 
1004     fprintf( m_pstream
, " reencodeISO def\n" ); 
1005     fprintf( m_pstream
, buffer 
); 
1006     fprintf( m_pstream
, " findfont\n" ); 
1008     fprintf( m_pstream
, "%f scalefont setfont\n", YLOG2DEVREL(m_font
.GetPointSize() * 1000) / 1000.0F
); 
1009                 // this is a hack - we must scale font size (in pts) according to m_scaleY but 
1010                 // YLOG2DEVREL works with wxCoord type (int or longint). Se we first convert font size 
1011                 // to 1/1000th of pt and then back. 
1014 void wxPostScriptDC::SetPen( const wxPen
& pen 
) 
1016     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1018     if (!pen
.Ok()) return; 
1020     int oldStyle 
= m_pen
.GetStyle(); 
1025     fprintf( m_pstream
, "%d setlinewidth\n", XLOG2DEVREL(m_pen
.GetWidth()) ); 
1027     fprintf( m_pstream
, "%d setlinewidth\n", XLOG2DEVREL(m_pen
.GetWidth()) ); 
1030      Line style - WRONG: 2nd arg is OFFSET 
1032      Here, I'm afraid you do not conceive meaning of parameters of 'setdash' 
1033      operator correctly. You should look-up this in the Red Book: the 2nd parame- 
1034      ter is not number of values in the array of the first one, but an offset 
1035      into this description of the pattern. I mean a real *offset* not index 
1036      into array. I.e. If the command is [3 4] 1 setdash   is used, then there 
1037      will be first black line *2* units wxCoord, then space 4 units, then the 
1038      pattern of *3* units black, 4 units space will be repeated. 
1041     static const char *dotted 
= "[2 5] 2"; 
1042     static const char *short_dashed 
= "[4 4] 2"; 
1043     static const char *wxCoord_dashed 
= "[4 8] 2"; 
1044     static const char *dotted_dashed 
= "[6 6 2 6] 4"; 
1046     const char *psdash 
= (char *) NULL
; 
1047     switch (m_pen
.GetStyle()) 
1049         case wxDOT
:           psdash 
= dotted
;         break; 
1050         case wxSHORT_DASH
:    psdash 
= short_dashed
;   break; 
1051         case wxLONG_DASH
:     psdash 
= wxCoord_dashed
;    break; 
1052         case wxDOT_DASH
:      psdash 
= dotted_dashed
;  break; 
1055         default:              psdash 
= "[] 0";         break; 
1058     if (oldStyle 
!= m_pen
.GetStyle()) 
1060         fprintf( m_pstream
, psdash 
); 
1061         fprintf( m_pstream
," setdash\n" ); 
1065     unsigned char red 
= m_pen
.GetColour().Red(); 
1066     unsigned char blue 
= m_pen
.GetColour().Blue(); 
1067     unsigned char green 
= m_pen
.GetColour().Green(); 
1071         // Anything not white is black 
1072         if (! (red 
== (unsigned char) 255 && 
1073                blue 
== (unsigned char) 255 && 
1074                green 
== (unsigned char) 255) ) 
1076             red 
= (unsigned char) 0; 
1077             green 
= (unsigned char) 0; 
1078             blue 
= (unsigned char) 0; 
1083     if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1085         double redPS 
= (double)(red
) / 255.0; 
1086         double bluePS 
= (double)(blue
) / 255.0; 
1087         double greenPS 
= (double)(green
) / 255.0; 
1090                 "%.8f %.8f %.8f setrgbcolor\n", 
1091                 redPS
, greenPS
, bluePS 
); 
1094         m_currentBlue 
= blue
; 
1095         m_currentGreen 
= green
; 
1099 void wxPostScriptDC::SetBrush( const wxBrush
& brush 
) 
1101     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1103     if (!brush
.Ok()) return; 
1108     unsigned char red 
= m_brush
.GetColour().Red(); 
1109     unsigned char blue 
= m_brush
.GetColour().Blue(); 
1110     unsigned char green 
= m_brush
.GetColour().Green(); 
1114         // Anything not white is black 
1115         if (! (red 
== (unsigned char) 255 && 
1116                blue 
== (unsigned char) 255 && 
1117                green 
== (unsigned char) 255) ) 
1119             red 
= (unsigned char) 0; 
1120             green 
= (unsigned char) 0; 
1121             blue 
= (unsigned char) 0; 
1126     if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1128         double redPS 
= (double)(red
) / 255.0; 
1129         double bluePS 
= (double)(blue
) / 255.0; 
1130         double greenPS 
= (double)(green
) / 255.0; 
1133                 "%.8f %.8f %.8f setrgbcolor\n", 
1134                 redPS
, greenPS
, bluePS 
); 
1137         m_currentBlue 
= blue
; 
1138         m_currentGreen 
= green
; 
1142 void wxPostScriptDC::DoDrawText( const wxString
& text
, wxCoord x
, wxCoord y 
) 
1144     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1146     wxCoord text_w
, text_h
, text_descent
; 
1148     GetTextExtent(text
, &text_w
, &text_h
, &text_descent
); 
1152     if (m_textForegroundColour
.Ok()) 
1154         unsigned char red 
= m_textForegroundColour
.Red(); 
1155         unsigned char blue 
= m_textForegroundColour
.Blue(); 
1156         unsigned char green 
= m_textForegroundColour
.Green(); 
1160             // Anything not white is black 
1161             if (! (red 
== (unsigned char) 255 && 
1162                         blue 
== (unsigned char) 255 && 
1163                         green 
== (unsigned char) 255)) 
1165                 red 
= (unsigned char) 0; 
1166                 green 
= (unsigned char) 0; 
1167                 blue 
= (unsigned char) 0; 
1171         // maybe setgray here ? 
1172         if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1174             double redPS 
= (double)(red
) / 255.0; 
1175             double bluePS 
= (double)(blue
) / 255.0; 
1176             double greenPS 
= (double)(green
) / 255.0; 
1179                     "%.8f %.8f %.8f setrgbcolor\n", 
1180                     redPS
, greenPS
, bluePS 
); 
1183             m_currentBlue 
= blue
; 
1184             m_currentGreen 
= green
; 
1188     int size 
= m_font
.GetPointSize(); 
1190 //    wxCoord by = y + (wxCoord)floor( double(size) * 2.0 / 3.0 ); // approximate baseline 
1191 //    commented by V. Slavik and replaced by accurate version 
1192 //        - note that there is still rounding error in text_descent! 
1193     wxCoord by 
= y 
+ size 
- text_descent
; // baseline 
1194     fprintf( m_pstream
, "%d %d moveto\n", XLOG2DEV(x
), YLOG2DEV(by
) ); 
1196     /* I don't know how to write char to a stream, so I use a mini string */ 
1200     fprintf( m_pstream
, "(" ); 
1201     const wxWX2MBbuf textbuf 
= text
.mb_str(); 
1202     int len 
= strlen(textbuf
); 
1204     for (i 
= 0; i 
< len
; i
++) 
1206         int c 
= (unsigned char) textbuf
[i
]; 
1207         if (c 
== ')' || c 
== '(' || c 
== '\\') 
1209             /* Cope with special characters */ 
1210             fprintf( m_pstream
, "\\" ); 
1211             tmpbuf
[0] = (char) c
; 
1212             fprintf( m_pstream
, tmpbuf 
); 
1214         else if ( c 
>= 128 ) 
1216             /* Cope with character codes > 127 */ 
1217             fprintf(m_pstream
, "\\%o", c
); 
1221             tmpbuf
[0] = (char) c
; 
1222             fprintf( m_pstream
, tmpbuf 
); 
1226     fprintf( m_pstream
, ") show\n" ); 
1228     if (m_font
.GetUnderlined()) 
1230         wxCoord uy 
= (wxCoord
)(y 
+ size 
- m_underlinePosition
); 
1239                 XLOG2DEV(x
), YLOG2DEV(uy
), 
1240                 (wxCoord
)m_underlineThickness
, 
1241                 XLOG2DEV(x 
+ text_w
), YLOG2DEV(uy
) ); 
1244     CalcBoundingBox( x
, y 
); 
1245     CalcBoundingBox( x 
+ size 
* text
.Length() * 2/3 , y 
); 
1248 void wxPostScriptDC::DoDrawRotatedText( const wxString
& text
, wxCoord x
, wxCoord y
, double angle 
) 
1252         DoDrawText(text
, x
, y
); 
1256     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1260     if (m_textForegroundColour
.Ok()) 
1262         unsigned char red 
= m_textForegroundColour
.Red(); 
1263         unsigned char blue 
= m_textForegroundColour
.Blue(); 
1264         unsigned char green 
= m_textForegroundColour
.Green(); 
1268             // Anything not white is black 
1269             if (! (red 
== (unsigned char) 255 && 
1270                    blue 
== (unsigned char) 255 && 
1271                    green 
== (unsigned char) 255)) 
1273                 red 
= (unsigned char) 0; 
1274                 green 
= (unsigned char) 0; 
1275                 blue 
= (unsigned char) 0; 
1279         // maybe setgray here ? 
1280         if (!(red 
== m_currentRed 
&& green 
== m_currentGreen 
&& blue 
== m_currentBlue
)) 
1282             double redPS 
= (double)(red
) / 255.0; 
1283             double bluePS 
= (double)(blue
) / 255.0; 
1284             double greenPS 
= (double)(green
) / 255.0; 
1287                     "%.8f %.8f %.8f setrgbcolor\n", 
1288                     redPS
, greenPS
, bluePS 
); 
1291             m_currentBlue 
= blue
; 
1292             m_currentGreen 
= green
; 
1296     int size 
= m_font
.GetPointSize(); 
1298     long by 
= y 
+ (long)floor( double(size
) * 2.0 / 3.0 ); // approximate baseline 
1300     // FIXME only correct for 90 degrees 
1301     fprintf(m_pstream
, "%d %d moveto\n", XLOG2DEV(x 
+ size
), YLOG2DEV(by
) ); 
1302     fprintf(m_pstream
, "%.8f rotate\n", angle
); 
1304     /* I don't know how to write char to a stream, so I use a mini string */ 
1308     fprintf( m_pstream
, "(" ); 
1309     const wxWX2MBbuf textbuf 
= text
.mb_str(); 
1310     int len 
= strlen(textbuf
); 
1312     for (i 
= 0; i 
< len
; i
++) 
1314         int c 
= (unsigned char) textbuf
[i
]; 
1315         if (c 
== ')' || c 
== '(' || c 
== '\\') 
1317             /* Cope with special characters */ 
1318             fprintf( m_pstream
, "\\" ); 
1319             tmpbuf
[0] = (char) c
; 
1320             fprintf( m_pstream
, tmpbuf 
); 
1322         else if ( c 
>= 128 ) 
1324             /* Cope with character codes > 127 */ 
1325             fprintf(m_pstream
, "\\%o", c
); 
1329             tmpbuf
[0] = (char) c
; 
1330             fprintf( m_pstream
, tmpbuf 
); 
1334     fprintf( m_pstream
, ") show\n" ); 
1335     fprintf( m_pstream
, "%.8f rotate\n", -angle 
); 
1337     if (m_font
.GetUnderlined()) 
1339         long uy 
= (long)(y 
+ size 
- m_underlinePosition
); 
1341         GetTextExtent(text
, &w
, &h
); 
1346                  "%ld setlinewidth\n" 
1350                  XLOG2DEV(x
), YLOG2DEV(uy
), 
1351                  (long)m_underlineThickness
, 
1352                  XLOG2DEV(x 
+ w
), YLOG2DEV(uy
) ); 
1355     CalcBoundingBox( x
, y 
); 
1356     CalcBoundingBox( x 
+ size 
* text
.Length() * 2/3 , y 
); 
1359 void wxPostScriptDC::SetBackground (const wxBrush
& brush
) 
1361     m_backgroundBrush 
= brush
; 
1364 void wxPostScriptDC::SetLogicalFunction (int WXUNUSED(function
)) 
1366     wxFAIL_MSG( wxT("wxPostScriptDC::SetLogicalFunction not implemented.") ); 
1369 void wxPostScriptDC::DoDrawSpline( wxList 
*points 
) 
1371     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1375     double a
, b
, c
, d
, x1
, y1
, x2
, y2
, x3
, y3
; 
1378     wxNode 
*node 
= points
->First(); 
1379     p 
= (wxPoint 
*)node
->Data(); 
1383     node 
= node
->Next(); 
1384     p 
= (wxPoint 
*)node
->Data(); 
1387     x3 
= a 
= (double)(x1 
+ c
) / 2; 
1388     y3 
= b 
= (double)(y1 
+ d
) / 2; 
1394             XLOG2DEV((wxCoord
)x1
), YLOG2DEV((wxCoord
)y1
), 
1395             XLOG2DEV((wxCoord
)x3
), YLOG2DEV((wxCoord
)y3
) ); 
1397     CalcBoundingBox( (wxCoord
)x1
, (wxCoord
)y1 
); 
1398     CalcBoundingBox( (wxCoord
)x3
, (wxCoord
)y3 
); 
1400     while ((node 
= node
->Next()) != NULL
) 
1402         q 
= (wxPoint 
*)node
->Data(); 
1410         x3 
= (double)(x2 
+ c
) / 2; 
1411         y3 
= (double)(y2 
+ d
) / 2; 
1414                 "%d %d %d %d %d %d DrawSplineSection\n", 
1415                 XLOG2DEV((wxCoord
)x1
), YLOG2DEV((wxCoord
)y1
), 
1416                 XLOG2DEV((wxCoord
)x2
), YLOG2DEV((wxCoord
)y2
), 
1417                 XLOG2DEV((wxCoord
)x3
), YLOG2DEV((wxCoord
)y3
) ); 
1419         CalcBoundingBox( (wxCoord
)x1
, (wxCoord
)y1 
); 
1420         CalcBoundingBox( (wxCoord
)x3
, (wxCoord
)y3 
); 
1424        At this point, (x2,y2) and (c,d) are the position of the 
1425        next-to-last and last point respectively, in the point list 
1431             XLOG2DEV((wxCoord
)c
), YLOG2DEV((wxCoord
)d
) ); 
1434 wxCoord 
wxPostScriptDC::GetCharWidth() const 
1436     // Chris Breeze: reasonable approximation using wxMODERN/Courier 
1437     return (wxCoord
) (GetCharHeight() * 72.0 / 120.0); 
1441 void wxPostScriptDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
1443     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1445     m_signX 
= (xLeftRight 
? 1 : -1); 
1446     m_signY 
= (yBottomUp  
? 1 : -1); 
1448     // FIXME there is no such function in MSW nor in OS2/PM 
1449 #if !defined(__WXMSW__) && !defined(__WXPM__) 
1450     ComputeScaleAndOrigin(); 
1454 void wxPostScriptDC::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
1456     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1462     wxDC::SetDeviceOrigin( x
, h
-y 
); 
1465 void wxPostScriptDC::DoGetSize(int* width
, int* height
) const 
1467     wxPaperSize id 
= m_printData
.GetPaperId(); 
1469     wxPrintPaperType 
*paper 
= wxThePrintPaperDatabase
->FindPaperType(id
); 
1471     if (!paper
) paper 
= wxThePrintPaperDatabase
->FindPaperType(wxPAPER_A4
); 
1477         w 
= paper
->GetSizeDeviceUnits().x
; 
1478         h 
= paper
->GetSizeDeviceUnits().y
; 
1481     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1488     if (width
) *width 
= w
; 
1489     if (height
) *height 
= h
; 
1492 void wxPostScriptDC::DoGetSizeMM(int *width
, int *height
) const 
1494     wxPaperSize id 
= m_printData
.GetPaperId(); 
1496     wxPrintPaperType 
*paper 
= wxThePrintPaperDatabase
->FindPaperType(id
); 
1498     if (!paper
) paper 
= wxThePrintPaperDatabase
->FindPaperType(wxPAPER_A4
); 
1504         w 
= paper
->GetWidth() / 10; 
1505         h 
= paper
->GetHeight() / 10; 
1508     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1515     if (width
) *width 
= w
; 
1516     if (height
) *height 
= h
; 
1519 // Resolution in pixels per logical inch 
1520 wxSize 
wxPostScriptDC::GetPPI(void) const 
1522     return wxSize(72, 72); 
1526 bool wxPostScriptDC::StartDoc( const wxString
& message 
) 
1528     wxCHECK_MSG( m_ok
, FALSE
, wxT("invalid postscript dc") ); 
1530     if (m_printData
.GetFilename() == "") 
1532         wxString filename 
= wxGetTempFileName("ps"); 
1533         m_printData
.SetFilename(filename
); 
1536     m_pstream 
= fopen( m_printData
.GetFilename().fn_str(), "w+" ); 
1540         wxMessageBox( _("Cannot open file for PostScript printing!"), _("Error"), wxOK 
); 
1547     fprintf( m_pstream
, "%%%%BeginProlog\n" ); 
1548     fprintf( m_pstream
, wxPostScriptHeaderEllipse 
); 
1549     fprintf( m_pstream
, wxPostScriptHeaderEllipticArc 
); 
1550     fprintf( m_pstream
, wxPostScriptHeaderColourImage 
); 
1551     fprintf( m_pstream
, wxPostScriptHeaderReencodeISO1 
); 
1552     fprintf( m_pstream
, wxPostScriptHeaderReencodeISO2 
); 
1553     if (wxPostScriptHeaderSpline
) 
1554         fprintf( m_pstream
, wxPostScriptHeaderSpline 
); 
1555     fprintf( m_pstream
, "%%%%EndProlog\n" ); 
1557     SetBrush( *wxBLACK_BRUSH 
); 
1558     SetPen( *wxBLACK_PEN 
); 
1559     SetBackground( *wxWHITE_BRUSH 
); 
1560     SetTextForeground( *wxBLACK 
); 
1562     // set origin according to paper size 
1563     SetDeviceOrigin( 0,0 ); 
1571 void wxPostScriptDC::EndDoc () 
1573     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1578         fprintf( m_pstream
, "grestore\n" ); 
1581     fclose( m_pstream 
); 
1582     m_pstream 
= (FILE *) NULL
; 
1584     wxChar 
*header_file 
= wxGetTempFileName("ps"); 
1586     m_pstream 
= fopen( wxConvFile
.cWX2MB(header_file
) , "w+" ); 
1588     fprintf( m_pstream
, "%%!PS-Adobe-2.0\n" );                     // PostScript magic strings 
1589     fprintf( m_pstream
, "%%%%Title: %s\n", (const char *)m_title
.mb_str() ); 
1590     fprintf( m_pstream
, "%%%%Creator: %s\n", (const char*)wxConvCurrent
->cWX2MB(wxTheApp
->argv
[0]) ); 
1591     fprintf( m_pstream
, "%%%%CreationDate: %s\n", (const char *)wxNow().mb_str() ); 
1594     if ( wxGetEmailAddress(userID
, sizeof(userID
)) ) 
1596         fprintf( m_pstream
, "%%%%For: %s ", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userID
) ); 
1597         wxChar userName
[245]; 
1598         if (wxGetUserName(userName
, sizeof(userName
))) 
1599             fprintf( m_pstream
, " (%s)", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userName
) ); 
1600         fprintf( m_pstream
, "\n" ); 
1602     else if ( wxGetUserName(userID
, sizeof(userID
)) ) 
1604         fprintf( m_pstream
, "%%%%For: %s\n", wxMBSTRINGCAST wxConvCurrent
->cWX2MB(userID
) );; 
1607     // THE FOLLOWING HAS BEEN CONTRIBUTED BY Andy Fyfe <andy@hyperparallel.com> 
1609     wxCoord wx_printer_translate_x
, wx_printer_translate_y
; 
1610     double wx_printer_scale_x
, wx_printer_scale_y
; 
1612     wx_printer_translate_x 
= (wxCoord
)m_printData
.GetPrinterTranslateX(); 
1613     wx_printer_translate_y 
= (wxCoord
)m_printData
.GetPrinterTranslateY(); 
1615     wx_printer_scale_x 
= m_printData
.GetPrinterScaleX(); 
1616     wx_printer_scale_y 
= m_printData
.GetPrinterScaleY(); 
1618     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1619         fprintf( m_pstream
, "%%%%Orientation: Landscape\n" ); 
1621         fprintf( m_pstream
, "%%%%Orientation: Portrait\n" ); 
1623     // Compute the bounding box.  Note that it is in the default user 
1624     // coordinate system, thus we have to convert the values. 
1625     wxCoord llx 
= (wxCoord
) ((XLOG2DEV(m_minX
)+wx_printer_translate_x
)*wx_printer_scale_x
); 
1626     wxCoord lly 
= (wxCoord
) ((YLOG2DEV(m_minY
)+wx_printer_translate_y
)*wx_printer_scale_y
); 
1627     wxCoord urx 
= (wxCoord
) ((XLOG2DEV(m_maxX
)+wx_printer_translate_x
)*wx_printer_scale_x
); 
1628     wxCoord ury 
= (wxCoord
) ((YLOG2DEV(m_maxY
)+wx_printer_translate_y
)*wx_printer_scale_y
); 
1630     // If we're landscape, our sense of "x" and "y" is reversed. 
1631     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1634         tmp 
= llx
; llx 
= lly
; lly 
= tmp
; 
1635         tmp 
= urx
; urx 
= ury
; ury 
= tmp
; 
1637         // We need either the two lines that follow, or we need to subtract 
1638         // min_x from real_translate_y, which is commented out below. 
1639         llx 
= llx 
- (wxCoord
)(m_minX
*wx_printer_scale_y
); 
1640         urx 
= urx 
- (wxCoord
)(m_minX
*wx_printer_scale_y
); 
1643     // The Adobe specifications call for integers; we round as to make 
1644     // the bounding larger. 
1646             "%%%%BoundingBox: %d %d %d %d\n", 
1647             (wxCoord
)floor((double)llx
), (wxCoord
)floor((double)lly
), 
1648             (wxCoord
)ceil((double)urx
), (wxCoord
)ceil((double)ury
) ); 
1649     fprintf( m_pstream
, "%%%%Pages: %d\n", (wxPageNumber 
- 1) ); 
1650     fprintf( m_pstream
, "%%%%EndComments\n\n" ); 
1652     // To check the correctness of the bounding box, postscript commands 
1653     // to draw a box corresponding to the bounding box are generated below. 
1654     // But since we typically don't want to print such a box, the postscript 
1655     // commands are generated within comments.  These lines appear before any 
1656     // adjustment of scale, rotation, or translation, and hence are in the 
1657     // default user coordinates. 
1658     fprintf( m_pstream
, "%% newpath\n" ); 
1659     fprintf( m_pstream
, "%% %d %d moveto\n", llx
, lly 
); 
1660     fprintf( m_pstream
, "%% %d %d lineto\n", urx
, lly 
); 
1661     fprintf( m_pstream
, "%% %d %d lineto\n", urx
, ury 
); 
1662     fprintf( m_pstream
, "%% %d %d lineto closepath stroke\n", llx
, ury 
); 
1664     fclose( m_pstream 
); 
1665     m_pstream 
= (FILE*) NULL
; 
1667     wxChar 
*tmp_file 
= wxGetTempFileName("ps"); 
1669     // Paste header Before wx_printer_file 
1670     wxConcatFiles (header_file
, m_printData
.GetFilename(), tmp_file 
); 
1671     wxRemoveFile( header_file 
); 
1672     wxRemoveFile( m_printData
.GetFilename() ); 
1673     wxRenameFile( tmp_file
, m_printData
.GetFilename() ); 
1675 #if defined(__X__) || defined(__WXGTK__) 
1678         wxString 
previewCommand(m_printData
.GetPreviewCommand()); 
1679         wxString 
printerCommand(m_printData
.GetPrinterCommand()); 
1680         wxString 
printerOptions(m_printData
.GetPrinterOptions()); 
1681         wxString 
filename(m_printData
.GetFilename()); 
1683         switch (m_printData
.GetPrintMode()) 
1685             case wxPRINT_MODE_PREVIEW
: 
1688                 argv
[0] = WXSTRINGCAST previewCommand
; 
1689                 argv
[1] = WXSTRINGCAST filename
; 
1690                 argv
[2] = (wxChar
*) NULL
; 
1691                 wxExecute( argv
, TRUE 
); 
1692                 wxRemoveFile( m_printData
.GetFilename() ); 
1695             case wxPRINT_MODE_PRINTER
: 
1699                 argv
[argc
++] = WXSTRINGCAST printerCommand
; 
1701                 // !SM! If we simply assign to argv[1] here, if printer options 
1702                 // are blank, we get an annoying and confusing message from lpr. 
1703                 wxChar 
*opts 
= WXSTRINGCAST printerOptions
; 
1705                     argv
[argc
++] = opts
; 
1707                 argv
[argc
++] = WXSTRINGCAST filename
; 
1708                 argv
[argc
++] = (wxChar 
*) NULL
; 
1709                 wxExecute( argv
, TRUE 
); 
1710                 wxRemoveFile( filename 
); 
1713             case wxPRINT_MODE_FILE
: 
1714             case wxPRINT_MODE_NONE
: 
1721 void wxPostScriptDC::StartPage() 
1723     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1725     fprintf( m_pstream
, "%%%%Page: %d\n", wxPageNumber
++ ); 
1727     //  What is this one supposed to do? RR. 
1728 //  *m_pstream << "matrix currentmatrix\n"; 
1730     // Added by Chris Breeze 
1732     // Each page starts with an "initgraphics" which resets the 
1733     // transformation and so we need to reset the origin 
1734     // (and rotate the page for landscape printing) 
1737     wxCoord translate_x
, translate_y
; 
1738     double scale_x
, scale_y
; 
1740     translate_x 
= (wxCoord
)m_printData
.GetPrinterTranslateX(); 
1741     translate_y 
= (wxCoord
)m_printData
.GetPrinterTranslateY(); 
1743     scale_x 
= m_printData
.GetPrinterScaleX(); 
1744     scale_y 
= m_printData
.GetPrinterScaleY(); 
1746     if (m_printData
.GetOrientation() == wxLANDSCAPE
) 
1749         GetSize( (int*) NULL
, &h 
); 
1751         fprintf( m_pstream
, "90 rotate\n" ); 
1753         // I copied this one from a PostScript tutorial, but to no avail. RR. 
1754         // fprintf( m_pstream, "90 rotate llx neg ury nef translate\n" ); 
1757     fprintf( m_pstream
, "%.8f %.8f scale\n", scale_x
, scale_y 
); 
1758     fprintf( m_pstream
, "%d %d translate\n", translate_x
, translate_y 
); 
1761 void wxPostScriptDC::EndPage () 
1763     wxCHECK_RET( m_ok 
&& m_pstream
, wxT("invalid postscript dc") ); 
1765     fprintf( m_pstream
, "showpage\n" ); 
1768 bool wxPostScriptDC::DoBlit( wxCoord xdest
, wxCoord ydest
, 
1769                            wxCoord fwidth
, wxCoord fheight
, 
1771                            wxCoord xsrc
, wxCoord ysrc
, 
1772                            int rop
, bool WXUNUSED(useMask
) ) 
1774     wxCHECK_MSG( m_ok 
&& m_pstream
, FALSE
, wxT("invalid postscript dc") ); 
1776     wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") ); 
1778     /* blit into a bitmap */ 
1779     wxBitmap 
bitmap( (int)fwidth
, (int)fheight 
); 
1781     memDC
.SelectObject(bitmap
); 
1782     memDC
.Blit(0, 0, fwidth
, fheight
, source
, xsrc
, ysrc
, rop
); /* TODO: Blit transparently? */ 
1783     memDC
.SelectObject(wxNullBitmap
); 
1785     /* draw bitmap. scaling and positioning is done there */ 
1786     DrawBitmap( bitmap
, xdest
, ydest 
); 
1791 wxCoord 
wxPostScriptDC::GetCharHeight() const 
1794         return  m_font
.GetPointSize(); 
1799 void wxPostScriptDC::DoGetTextExtent(const wxString
& string
, 
1800                                      wxCoord 
*x
, wxCoord 
*y
, 
1801                                      wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1802                                      wxFont 
*theFont 
) const 
1804     wxFont 
*fontToUse 
= theFont
; 
1806     if (!fontToUse
) fontToUse 
= (wxFont
*) &m_font
; 
1808     wxCHECK_RET( fontToUse
, wxT("GetTextExtent: no font defined") ); 
1809     wxCHECK_RET( x
, wxT("GetTextExtent: x == NULL") ); 
1810     wxCHECK_RET( y
, wxT("GetTextExtent: y == NULL") ); 
1812     const wxWX2MBbuf strbuf 
= string
.mb_str(); 
1814 #if !wxUSE_AFM_FOR_POSTSCRIPT 
1815     /* Provide a VERY rough estimate (avoid using it). 
1816      * Produces accurate results for mono-spaced font 
1817      * such as Courier (aka wxMODERN) */ 
1822         height 
= fontToUse
->GetPointSize(); 
1825         *x 
= strlen (strbuf
) * height 
* 72 / 120; 
1827         *y 
= (wxCoord
) (height 
* 1.32);    /* allow for descender */ 
1828     if (descent
) *descent 
= 0; 
1829     if (externalLeading
) *externalLeading 
= 0; 
1832     /* method for calculating string widths in postscript: 
1833     /  read in the AFM (adobe font metrics) file for the 
1834     /  actual font, parse it and extract the character widths 
1835     /  and also the descender. this may be improved, but for now 
1836     /  it works well. the AFM file is only read in if the 
1837     /  font is changed. this may be chached in the future. 
1838     /  calls to GetTextExtent with the font unchanged are rather 
1841     /  for each font and style used there is an AFM file necessary. 
1842     /  currently i have only files for the roman font family. 
1843     /  I try to get files for the other ones! 
1845     /  CAVE: the size of the string is currently always calculated 
1846     /        in 'points' (1/72 of an inch). this should later on be 
1847     /        changed to depend on the mapping mode. 
1848     /  CAVE: the path to the AFM files must be set before calling this 
1849     /        function. this is usually done by a call like the following: 
1850     /        wxSetAFMPath("d:\\wxw161\\afm\\"); 
1854     /    wxPostScriptDC dc(NULL, TRUE); 
1856     /      wxSetAFMPath("d:\\wxw161\\afm\\"); 
1857     /      dc.StartDoc("Test"); 
1860     /      dc.SetFont(new wxFont(10, wxROMAN, wxNORMAL, wxNORMAL)); 
1861     /      dc.GetTextExtent("Hallo",&w,&h); 
1866     /  by steve (stefan.hammes@urz.uni-heidelberg.de) 
1868     /  updated: 14.05.95 */ 
1870     /* these static vars are for storing the state between calls */ 
1871     static int lastFamily
= INT_MIN
; 
1872     static int lastSize
= INT_MIN
; 
1873     static int lastStyle
= INT_MIN
; 
1874     static int lastWeight
= INT_MIN
; 
1875     static int lastDescender 
= INT_MIN
; 
1876     static int lastWidths
[256]; /* widths of the characters */ 
1878     double UnderlinePosition 
= 0.0; 
1879     double UnderlineThickness 
= 0.0; 
1881     /* get actual parameters */ 
1882     const int Family 
= fontToUse
->GetFamily(); 
1883     const int Size 
=   fontToUse
->GetPointSize(); 
1884     const int Style 
=  fontToUse
->GetStyle(); 
1885     const int Weight 
= fontToUse
->GetWeight(); 
1887     /* if we have another font, read the font-metrics */ 
1888     if (Family
!=lastFamily 
|| Size
!=lastSize 
|| Style
!=lastStyle 
|| Weight
!=lastWeight
) 
1890         /* store actual values */ 
1891         lastFamily 
= Family
; 
1894         lastWeight 
= Weight
; 
1896         char *name 
= (char*) NULL
; 
1902                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "CourBoO"; 
1903                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "CourBo"; 
1904                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "Cour0"; 
1910                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "TimesBoO"; 
1911                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "TimesBo"; 
1912                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "TimesO"; 
1913                     else name 
= "TimesRo"; 
1918                     if ((Style 
== wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "HelvBoO"; 
1919                     else if ((Style 
!= wxITALIC
) && (Weight 
== wxBOLD
)) name 
= "HelvBo"; 
1920                     else if ((Style 
== wxITALIC
) && (Weight 
!= wxBOLD
)) name 
= "Helv0"; 
1926         /* get the directory of the AFM files */ 
1927         wxString afmName 
= wxEmptyString
; 
1928         if (!m_printData
.GetFontMetricPath().IsEmpty()) 
1930             afmName 
= m_printData
.GetFontMetricPath(); 
1933         /* 2. open and process the file 
1934            /  a short explanation of the AFM format: 
1935            /  we have for each character a line, which gives its size 
1938            /    C 63 ; WX 444 ; N question ; B 49 -14 395 676 ; 
1940            /  that means, we have a character with ascii code 63, and width 
1941            /  (444/1000 * fontSize) points. 
1942            /  the other data is ignored for now! 
1944            /  when the font has changed, we read in the right AFM file and store the 
1945            /  character widths in an array, which is processed below (see point 3.). */ 
1947         /* new elements JC Sun Aug 25 23:21:44 MET DST 1996 */ 
1949         afmName 
<< name 
<< wxT(".afm"); 
1950         FILE *afmFile 
= wxFopen(afmName
,wxT("r")); 
1953            afmName 
= wxThePrintSetupData
->GetAFMPath(); 
1954            afmName 
<< wxFILE_SEP_PATH 
<< name 
<< wxT(".afm"); 
1955            afmFile 
= wxFopen(afmName
,wxT("r")); 
1961         /* please do NOT change the line above to "else if (afmFile==NULL)" - 
1962            - afmFile = fopen() may fail and in that case the next if branch 
1963            MUST be executed - and it would not if there was "else" */ 
1965            afmName 
= wxINSTALL_PREFIX
; 
1966            afmName 
<<  wxFILE_SEP_PATH
 
1967                    << wxT("share") << wxFILE_SEP_PATH
 
1968                    << wxT("wx") << wxFILE_SEP_PATH
 
1969                    << wxT("afm") << wxFILE_SEP_PATH
 
1970                    << name 
<< wxT(".afm"); 
1971            afmFile 
= wxFopen(afmName
,wxT("r")); 
1978             wxLogDebug( wxT("GetTextExtent: can't open AFM file '%hs'\n"), afmName
.c_str() ); 
1979             wxLogDebug( wxT("               using approximate values\n")); 
1980             for (int i
=0; i
<256; i
++) lastWidths
[i
] = 500; /* an approximate value */ 
1981             lastDescender 
= -150; /* dito. */ 
1985             /* init the widths array */ 
1986             for(int i
=0; i
<256; i
++) lastWidths
[i
] = INT_MIN
; 
1987             /* some variables for holding parts of a line */ 
1988             char cString
[10],semiString
[10],WXString
[10],descString
[20]; 
1989             char upString
[30], utString
[30], encString
[50]; 
1992             /* read in the file and parse it */ 
1993             while(fgets(line
,sizeof(line
),afmFile
)!=NULL
) 
1995                 /* A.) check for descender definition */ 
1996                 if (strncmp(line
,"Descender",9)==0) 
1998                     if ((sscanf(line
,"%s%d",descString
,&lastDescender
)!=2) || 
1999                             (strcmp(descString
,"Descender")!=0)) 
2001                         wxLogDebug( wxT("AFM-file '%hs': line '%hs' has error (bad descender)\n"), afmName
.c_str(),line 
); 
2004                 /* JC 1.) check for UnderlinePosition */ 
2005                 else if(strncmp(line
,"UnderlinePosition",17)==0) 
2007                     if ((sscanf(line
,"%s%lf",upString
,&UnderlinePosition
)!=2) || 
2008                             (strcmp(upString
,"UnderlinePosition")!=0)) 
2010                         wxLogDebug( wxT("AFM-file '%hs': line '%hs' has error (bad UnderlinePosition)\n"), afmName
.c_str(), line 
); 
2013                 /* JC 2.) check for UnderlineThickness */ 
2014                 else if(strncmp(line
,"UnderlineThickness",18)==0) 
2016                     if ((sscanf(line
,"%s%lf",utString
,&UnderlineThickness
)!=2) || 
2017                             (strcmp(utString
,"UnderlineThickness")!=0)) 
2019                         wxLogDebug( wxT("AFM-file '%hs': line '%hs' has error (bad UnderlineThickness)\n"), afmName
.c_str(), line 
); 
2022                 /* JC 3.) check for EncodingScheme */ 
2023                 else if(strncmp(line
,"EncodingScheme",14)==0) 
2025                     if ((sscanf(line
,"%s%s",utString
,encString
)!=2) || 
2026                             (strcmp(utString
,"EncodingScheme")!=0)) 
2028                         wxLogDebug( wxT("AFM-file '%hs': line '%hs' has error (bad EncodingScheme)\n"), afmName
.c_str(), line 
); 
2030                     else if (strncmp(encString
, "AdobeStandardEncoding", 21)) 
2032                         wxLogDebug( wxT("AFM-file '%hs': line '%hs' has error (unsupported EncodingScheme %hs)\n"), 
2033                                 afmName
.c_str(),line
, encString
); 
2036                 /* B.) check for char-width */ 
2037                 else if(strncmp(line
,"C ",2)==0) 
2039                     if (sscanf(line
,"%s%d%s%s%d",cString
,&ascii
,semiString
,WXString
,&cWidth
)!=5) 
2041                         wxLogDebug(wxT("AFM-file '%hs': line '%hs' has an error (bad character width)\n"),afmName
.c_str(),line
); 
2043                     if(strcmp(cString
,"C")!=0 || strcmp(semiString
,";")!=0 || strcmp(WXString
,"WX")!=0) 
2045                         wxLogDebug(wxT("AFM-file '%hs': line '%hs' has a format error\n"),afmName
.c_str(),line
); 
2047                     /* printf("            char '%c'=%d has width '%d'\n",ascii,ascii,cWidth); */ 
2048                     if (ascii
>=0 && ascii
<256) 
2050                         lastWidths
[ascii
] = cWidth
; /* store width */ 
2054                         /* MATTHEW: this happens a lot; don't print an error */ 
2055                         /* wxLogDebug("AFM-file '%s': ASCII value %d out of range\n",afmName.c_str(),ascii); */ 
2058                 /* C.) ignore other entries. */ 
2062         /* hack to compute correct values for german 'Umlaute' 
2063            /  the correct way would be to map the character names 
2064            /  like 'adieresis' to corresp. positions of ISOEnc and read 
2065            /  these values from AFM files, too. Maybe later ... */ 
2066         lastWidths
[196] = lastWidths
['A'];  // Ä 
2067         lastWidths
[228] = lastWidths
['a'];  // ä 
2068         lastWidths
[214] = lastWidths
['O'];  // Ö 
2069         lastWidths
[246] = lastWidths
['o'];  // ö 
2070         lastWidths
[220] = lastWidths
['U'];  // Ü 
2071         lastWidths
[252] = lastWidths
['u'];  // ü 
2072         lastWidths
[223] = lastWidths
[251];  // ß 
2075     /* JC: calculate UnderlineThickness/UnderlinePosition */ 
2077         // VS: dirty, but is there any better solution? 
2079         pt 
= (double*) &m_underlinePosition
; 
2080         *pt 
= UnderlinePosition 
* fontToUse
->GetPointSize() / 1000.0f
; 
2081         pt 
= (double*) &m_underlineThickness
; 
2082         *pt 
= UnderlineThickness 
* fontToUse
->GetPointSize() / 1000.0f 
* m_scaleFactor
; 
2085     /* 3. now the font metrics are read in, calc size this 
2086        /  is done by adding the widths of the characters in the 
2087        /  string. they are given in 1/1000 of the size! */ 
2090     wxCoord height
=Size
; /* by default */ 
2092     for(p
=(unsigned char *)wxMBSTRINGCAST strbuf
; *p
; p
++) 
2094         if(lastWidths
[*p
]== INT_MIN
) 
2096             wxLogDebug(wxT("GetTextExtent: undefined width for character '%hc' (%d)\n"), *p
,*p
); 
2097             widthSum 
+= (lastWidths
[' ']/1000.0F 
* Size
); /* assume space */ 
2101             widthSum 
+= ((lastWidths
[*p
]/1000.0F
)*Size
); 
2105     /* add descender to height (it is usually a negative value) */ 
2106     //if (lastDescender != INT_MIN) 
2108     //    height += (wxCoord)(((-lastDescender)/1000.0F) * Size); /* MATTHEW: forgot scale */ 
2110     // - commented by V. Slavik - height already contains descender in it 
2111     //   (judging from few experiments) 
2113     /* return size values */ 
2115         *x 
= (wxCoord
)widthSum
; 
2119     /* return other parameters */ 
2122         if(lastDescender
!=INT_MIN
) 
2124             *descent 
= (wxCoord
)(((-lastDescender
)/1000.0F
) * Size
); /* MATTHEW: forgot scale */ 
2132     /* currently no idea how to calculate this! */ 
2133     if (externalLeading
) *externalLeading 
= 0; 
2138 // Determine the Default Postscript Previewer 
2139 // available on the platform 
2140 #if defined(__SUN__) && defined(__XVIEW__) 
2141 // OpenWindow/NeWS's Postscript Previewer 
2142 # define PS_VIEWER_PROG "pageview" 
2143 #elif defined(__VMS__) 
2144 #define PS_VIEWER_PROG "view/format=ps/select=x_display" 
2145 #elif defined(__SGI__) 
2146 // SGI's Display Postscript Previewer 
2147 //# define PS_VIEWER_PROG "dps" 
2148 # define PS_VIEWER_PROG "xpsview" 
2149 #elif defined(__X__) || defined(__WXGTK__) 
2150 // Front-end to ghostscript 
2151 # define PS_VIEWER_PROG "ghostview" 
2153 // Windows ghostscript/ghostview 
2154 # define PS_VIEWER_PROG "gsview" 
2157 wxPrintSetupData 
*wxThePrintSetupData 
= (wxPrintSetupData 
*) NULL
; 
2159 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptDC
, wxDC
) 
2160 IMPLEMENT_DYNAMIC_CLASS(wxPrintSetupData
, wxObject
) 
2162 // Redundant now I think 
2164 IMPLEMENT_CLASS(wxPostScriptPrintDialog
, wxDialog
) 
2166 wxPostScriptPrintDialog::wxPostScriptPrintDialog (wxWindow 
*parent
, const wxString
& title
, 
2167             const wxPoint
& pos
, const wxSize
& size
, wxCoord style
): 
2168    wxDialog(parent
, -1, title
, pos
, size
, style
) 
2170    wxBeginBusyCursor(); 
2175       *orientation 
= new wxString
[2], 
2176       *print_modes 
= new wxString
[3]; 
2178    wxCoord wx_printer_translate_x
, wx_printer_translate_y
; 
2179    double wx_printer_scale_x
, wx_printer_scale_y
; 
2181    orientation
[0] = _("Portrait"); 
2182    orientation
[1] = _("Landscape"); 
2184    print_modes
[0] = _("Send to Printer"); 
2185    print_modes
[1] = _("Print to File"); 
2186    print_modes
[2] = _("Preview Only"); 
2190    wxButton 
*okBut 
= new wxButton (this, wxID_OK
, _("OK"), wxPoint(5, 5)); 
2191    (void) new wxButton (this, wxID_CANCEL
, _("Cancel"), wxPoint(40, 5)); 
2192    okBut
->SetDefault(); 
2195 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
2196    (void) new wxStaticText( this, -1, _("Printer Command: "), 
2198    (void) new wxTextCtrl( this, wxID_PRINTER_COMMAND
, wxThePrintSetupData
->GetPrinterCommand(), 
2199                           wxPoint(100, yPos
), wxSize(100, -1) ); 
2201    (void) new wxStaticText( this, -1, _("Printer Options: "), 
2202                             wxPoint(210, yPos
) ); 
2203    (void) new wxTextCtrl( this, wxID_PRINTER_OPTIONS
, wxThePrintSetupData
->GetPrinterOptions(), 
2204                           wxPoint(305, yPos
), wxSize(150, -1) ); 
2210    wxRadioBox 
*radio0 
= new wxRadioBox(this, wxID_PRINTER_ORIENTATION
, "Orientation: ", wxPoint(5, yPos
), wxSize(-1,-1), 
2211                                        2,orientation
,2,wxRA_SPECIFY_ROWS
); 
2212    radio0
->SetSelection((int)wxThePrintSetupData
->GetPrinterOrientation() - 1); 
2214   // @@@ Configuration hook 
2215    if ( !wxThePrintSetupData
->GetPrintPreviewCommand() ) 
2216       wxThePrintSetupData
->SetPrintPreviewCommand(PS_VIEWER_PROG
); 
2218    //   wxGetResource ("wxWindows", "PSView", &wxThePrintSetupData->m_previewCommand); 
2220    features 
= (wxThePrintSetupData
->GetPrintPreviewCommand() && 
2221                *wxThePrintSetupData
->GetPrintPreviewCommand()) ? 3 : 2; 
2223    wxRadioBox 
*radio1 
= new wxRadioBox(this, wxID_PRINTER_MODES
, _("PostScript:"), 
2225                                        wxSize(-1,-1), features
, 
2226                                        print_modes
, features
, wxRA_SPECIFY_ROWS
); 
2229    radio1
->Enable(0, FALSE
); 
2230    if (wxThePrintSetupData
->GetPrintPreviewCommand() && *wxThePrintSetupData
->GetPrintPreviewCommand()) 
2231       radio1
->Enable(2, FALSE
); 
2234    radio1
->SetSelection((int)wxThePrintSetupData
->GetPrinterMode()); 
2235    wxThePrintSetupData
->GetPrinterTranslation(&wx_printer_translate_x
, &wx_printer_translate_y
); 
2236    wxThePrintSetupData
->GetPrinterScaling(&wx_printer_scale_x
, &wx_printer_scale_y
); 
2238    sprintf (buf
, "%.2f", wx_printer_scale_x
); 
2241    (void) new wxStaticText(this, -1, _("X Scaling"), wxPoint(5, yPos
)); 
2242    /* wxTextCtrl *text1 = */ (void) new wxTextCtrl(this, wxID_PRINTER_X_SCALE
, buf
, wxPoint(100, yPos
), wxSize(100, -1)); 
2244    sprintf (buf
, "%.2f", wx_printer_scale_y
); 
2245    (void) new wxStaticText(this, -1, _("Y Scaling"), wxPoint(220, yPos
)); 
2246    /* wxTextCtrl *text2 = */ (void) new wxTextCtrl(this, wxID_PRINTER_Y_SCALE
, buf
, wxPoint(320, yPos
), wxSize(100, -1)); 
2250    (void) new wxStaticText(this, -1, _("X Translation"), wxPoint(5, yPos
)); 
2251    sprintf (buf
, "%.2d", wx_printer_translate_x
); 
2252    /* wxTextCtrl *text3 = */ (void) new wxTextCtrl(this, wxID_PRINTER_X_TRANS
, buf
, wxPoint(100, yPos
), wxSize(100, -1)); 
2254    (void) new wxStaticText(this, -1, _("Y Translation"), wxPoint(220, yPos
)); 
2255    sprintf (buf
, "%.2d", wx_printer_translate_y
); 
2256    /* wxTextCtrl *text4 = */ (void) new wxTextCtrl(this, wxID_PRINTER_Y_TRANS
, buf
, wxPoint(320, yPos
), wxSize(100, -1)); 
2260    delete[] orientation
; 
2261    delete[] print_modes
; 
2266 int wxPostScriptPrintDialog::ShowModal () 
2268   if ( wxDialog::ShowModal() == wxID_OK 
) 
2270 //    wxTextCtrl *text0 = (wxTextCtrl *)FindWindow(wxID_PRINTER_OPTIONS); 
2271       wxTextCtrl 
*text1 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_X_SCALE
); 
2272       wxTextCtrl 
*text2 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_Y_SCALE
); 
2273       wxTextCtrl 
*text3 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_X_TRANS
); 
2274       wxTextCtrl 
*text4 
= (wxTextCtrl 
*)FindWindow(wxID_PRINTER_Y_TRANS
); 
2275 //    wxTextCtrl *text_prt = (wxTextCtrl *)FindWindow(wxID_PRINTER_COMMAND); 
2276       wxRadioBox 
*radio0 
= (wxRadioBox 
*)FindWindow(wxID_PRINTER_ORIENTATION
); 
2277       wxRadioBox 
*radio1 
= (wxRadioBox 
*)FindWindow(wxID_PRINTER_MODES
); 
2279       StringToDouble (WXSTRINGCAST text1
->GetValue (), &wxThePrintSetupData
->m_printerScaleX
); 
2280       StringToDouble (WXSTRINGCAST text2
->GetValue (), &wxThePrintSetupData
->m_printerScaleY
); 
2283       StringToLong (WXSTRINGCAST text3
->GetValue (), &dummy
); 
2284       wxThePrintSetupData
->m_printerTranslateX 
= (wxCoord
)dummy
; 
2285       StringToLong (WXSTRINGCAST text4
->GetValue (), &dummy
); 
2286       wxThePrintSetupData
->m_printerTranslateY 
= (wxCoord
)dummy
; 
2289       //      wxThePrintSetupData->SetPrinterOptions(WXSTRINGCAST text0->GetValue ()); 
2290       //      wxThePrintSetupData->SetPrinterCommand(WXSTRINGCAST text_prt->GetValue ()); 
2293       wxThePrintSetupData
->SetPrinterOrientation((radio0
->GetSelection() == 1 ? wxLANDSCAPE 
: wxPORTRAIT
)); 
2296       switch ( radio1
->GetSelection() ) { 
2297         case 0: wxThePrintSetupData
->SetPrinterMode(PS_PRINTER
); break; 
2298         case 1:  wxThePrintSetupData
->SetPrinterMode(PS_FILE
); break; 
2299         case 2: wxThePrintSetupData
->SetPrinterMode(PS_PREVIEW
); break; 
2308 // PostScript printer settings 
2309 // RETAINED FOR BACKWARD COMPATIBILITY 
2310 void wxSetPrinterCommand(const wxString
& cmd
) 
2312   wxThePrintSetupData
->SetPrinterCommand(cmd
); 
2315 void wxSetPrintPreviewCommand(const wxString
& cmd
) 
2317   wxThePrintSetupData
->SetPrintPreviewCommand(cmd
); 
2320 void wxSetPrinterOptions(const wxString
& flags
) 
2322   wxThePrintSetupData
->SetPrinterOptions(flags
); 
2325 void wxSetPrinterFile(const wxString
& f
) 
2327   wxThePrintSetupData
->SetPrinterFile(f
); 
2330 void wxSetPrinterOrientation(int orient
) 
2332   wxThePrintSetupData
->SetPrinterOrientation(orient
); 
2335 void wxSetPrinterScaling(double x
, double y
) 
2337   wxThePrintSetupData
->SetPrinterScaling(x
, y
); 
2340 void wxSetPrinterTranslation(wxCoord x
, wxCoord y
) 
2342   wxThePrintSetupData
->SetPrinterTranslation(x
, y
); 
2345 // 1 = Preview, 2 = print to file, 3 = send to printer 
2346 void wxSetPrinterMode(int mode
) 
2348   wxThePrintSetupData
->SetPrinterMode(mode
); 
2351 void wxSetAFMPath(const wxString
& f
) 
2353   wxThePrintSetupData
->SetAFMPath(f
); 
2356 // Get current values 
2357 wxString 
wxGetPrinterCommand() 
2359   return wxThePrintSetupData
->GetPrinterCommand(); 
2362 wxString 
wxGetPrintPreviewCommand() 
2364   return wxThePrintSetupData
->GetPrintPreviewCommand(); 
2367 wxString 
wxGetPrinterOptions() 
2369   return wxThePrintSetupData
->GetPrinterOptions(); 
2372 wxString 
wxGetPrinterFile() 
2374   return wxThePrintSetupData
->GetPrinterFile(); 
2377 int wxGetPrinterOrientation() 
2379   return wxThePrintSetupData
->GetPrinterOrientation(); 
2382 void wxGetPrinterScaling(double* x
, double* y
) 
2384   wxThePrintSetupData
->GetPrinterScaling(x
, y
); 
2387 void wxGetPrinterTranslation(wxCoord 
*x
, wxCoord 
*y
) 
2389   wxThePrintSetupData
->GetPrinterTranslation(x
, y
); 
2392 int wxGetPrinterMode() 
2394   return wxThePrintSetupData
->GetPrinterMode(); 
2397 wxString 
wxGetAFMPath() 
2399   return wxThePrintSetupData
->GetAFMPath(); 
2406 wxPrintSetupData::wxPrintSetupData() 
2408   m_printerOrient 
= wxPORTRAIT
; 
2409   m_printerScaleX 
= (double)1.0; 
2410   m_printerScaleY 
= (double)1.0; 
2411   m_printerTranslateX 
= 0; 
2412   m_printerTranslateY 
= 0; 
2413   m_printerMode 
= wxPRINT_MODE_FILE
; 
2414   m_printColour 
= TRUE
; 
2417 wxPrintSetupData::~wxPrintSetupData() 
2421 void wxPrintSetupData::operator=(wxPrintSetupData
& data
) 
2423   SetPrinterCommand(data
.GetPrinterCommand()); 
2424   SetPrintPreviewCommand(data
.GetPrintPreviewCommand()); 
2425   SetPrinterOptions(data
.GetPrinterOptions()); 
2427   data
.GetPrinterTranslation(&x
, &y
); 
2428   SetPrinterTranslation(x
, y
); 
2431   data
.GetPrinterScaling(&x1
, &y1
); 
2432   SetPrinterScaling(x1
, y1
); 
2434   SetPrinterOrientation(data
.GetPrinterOrientation()); 
2435   SetPrinterMode(data
.GetPrinterMode()); 
2436   SetAFMPath(data
.GetAFMPath()); 
2437   SetPaperName(data
.GetPaperName()); 
2438   SetColour(data
.GetColour()); 
2441 // Initialize from a wxPrintData object (wxPrintData should now be used instead of wxPrintSetupData). 
2442 void wxPrintSetupData::operator=(const wxPrintData
& data
) 
2444     SetPrinterCommand(data
.GetPrinterCommand()); 
2445     SetPrintPreviewCommand(data
.GetPreviewCommand()); 
2446     SetPrinterOptions(data
.GetPrinterOptions()); 
2447     SetPrinterTranslation(data
.GetPrinterTranslateX(), data
.GetPrinterTranslateY()); 
2448     SetPrinterScaling(data
.GetPrinterScaleX(), data
.GetPrinterScaleY()); 
2449     SetPrinterOrientation(data
.GetOrientation()); 
2450     SetPrinterMode((int) data
.GetPrintMode()); 
2451     SetAFMPath(data
.GetFontMetricPath()); 
2452     SetPaperName(wxThePrintPaperDatabase
->ConvertIdToName(data
.GetPaperId())); 
2453     SetColour(data
.GetColour()); 
2454     SetPrinterFile(data
.GetFilename()); 
2457 void wxInitializePrintSetupData(bool init
) 
2461     wxThePrintSetupData 
= new wxPrintSetupData
; 
2463     wxThePrintSetupData
->SetPrintPreviewCommand(PS_VIEWER_PROG
); 
2464     wxThePrintSetupData
->SetPrinterOrientation(wxPORTRAIT
); 
2465     wxThePrintSetupData
->SetPrinterMode(wxPRINT_MODE_PREVIEW
); 
2466     wxThePrintSetupData
->SetPaperName(_("A4 sheet, 210 x 297 mm")); 
2468     // Could have a .ini file to read in some defaults 
2469     // - and/or use environment variables, e.g. WXWIN 
2471     wxThePrintSetupData
->SetPrinterCommand("print"); 
2472     wxThePrintSetupData
->SetPrinterOptions("/nonotify/queue=psqueue"); 
2473     wxThePrintSetupData
->SetAFMPath("sys$ps_font_metrics:"); 
2476     wxThePrintSetupData
->SetPrinterCommand("print"); 
2477     wxThePrintSetupData
->SetAFMPath("c:\\windows\\system\\"); 
2478     wxThePrintSetupData
->SetPrinterOptions(""); 
2480 #if !defined(__VMS__) && !defined(__WXMSW__) 
2481     wxThePrintSetupData
->SetPrinterCommand("lpr"); 
2482     wxThePrintSetupData
->SetPrinterOptions(""); 
2483     wxThePrintSetupData
->SetAFMPath(""); 
2488     if (wxThePrintSetupData
) 
2489       delete wxThePrintSetupData
; 
2490      wxThePrintSetupData 
= (wxPrintSetupData 
*) NULL
; 
2494 // A module to allow initialization/cleanup of PostScript-related 
2495 // things without calling these functions from app.cpp. 
2497 class WXDLLEXPORT wxPostScriptModule
: public wxModule
 
2499 DECLARE_DYNAMIC_CLASS(wxPostScriptModule
) 
2501     wxPostScriptModule() {} 
2506 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptModule
, wxModule
) 
2509  * Initialization/cleanup module 
2512 bool wxPostScriptModule::OnInit() 
2514     wxInitializePrintSetupData(); 
2519 void wxPostScriptModule::OnExit() 
2521     wxInitializePrintSetupData(FALSE
); 
2528   // wxUSE_PRINTING_ARCHITECTURE