Back to index

plt-scheme  4.2.1
PSDC.cxx
Go to the documentation of this file.
00001 /*
00002  * File:      wb_ps.cc
00003  * Purpose:     Device context implementation (PostScript)
00004  * Author:      Julian Smart
00005  * Created:     1993
00006  * Updated:   August 1994
00007  * Copyright:   (c) 2004-2009 PLT Scheme Inc.
00008  * Copyright:   (c) 1993, AIAI, University of Edinburgh
00009  */
00010 
00011 /* This file is the same for all three version of wxWindows from
00012    PLT. */
00013 
00014 #if defined(_MSC_VER)
00015 # include "wx.h"
00016 #else
00017 
00018 #ifdef wx_xt
00019 # define  Uses_XLib
00020 # define  Uses_wxList
00021 # define  Uses_wxWindowDC
00022 # define  Uses_wxMemoryDC
00023 # define  Uses_wxPostScriptDC
00024 # define  Uses_wxPrintSetup
00025 # define  Uses_wxFontNameDirectory
00026 # define  Uses_wxDialogBox
00027 # define  Uses_wxButton
00028 # define  Uses_wxRadioBox
00029 # define  Uses_wxText
00030 # define  Uses_wxChoice
00031 # define  Uses_wxCheckBox
00032 # include "wx.h"
00033 
00034 # include <math.h>
00035 # include <string.h>
00036 
00037 #else
00038 
00039 # ifdef __GNUG__
00040 # pragma implementation "wx_dcps.h"
00041 # pragma implementation
00042 # pragma interface
00043 #endif
00044 
00045 # include "common.h"
00046 # include "wx_frame.h"
00047 # include "wx_dcps.h"
00048 # include "wx_dcmem.h"
00049 # include "wx_utils.h"
00050 # include "wx_dialg.h"
00051 # include "wx_cmdlg.h"
00052 # include "wx_main.h"
00053 # include "wx_lbox.h"
00054 # include "wx_rbox.h"
00055 # include "wx_buttn.h"
00056 # include "wx_choic.h"
00057 # include "wx_check.h"
00058 # include "wx_messg.h"
00059 
00060 #ifdef wx_mac
00061 # include "wx_print.h"
00062 #endif
00063 
00064 #endif
00065 #endif
00066 
00067 #include "wx_rgn.h"
00068 #include "../mzscheme/include/scheme.h"
00069 
00070 extern void *wxPostScriptDrawText(Scheme_Object *f, const char *fontname, 
00071                                   const char *text, int dt, Bool combine, int use16, 
00072                                   double font_size, int symbol_map, void *used_fonts);
00073 extern void wxPostScriptGetTextExtent(const char *fontname, 
00074                                   const char *text, int dt, int len, Bool combine, int use16, 
00075                                   double font_size,
00076                                   double *x, double *y, double *descent, double *topSpace,
00077                                   int symbol_map);
00078 extern char *wxPostScriptFixupFontName(const char *fontname);
00079 extern Bool wxPostScriptGlyphExists(const char *fontname, int c, int symbol_map);
00080 extern void *wxPostScriptRecordFont(const char *fontname, void *used_fonts);
00081 extern char *wxPostScriptFontsToString(void *used_fonts);
00082 
00083 # define YSCALE(y) ((paper_h) - ((y) * user_scale_y + device_origin_y))
00084 # define XSCALE(x) ((x) * user_scale_x + device_origin_x)
00085 # define YOFFSET(y) ((paper_h) - ((y) + device_origin_y))
00086 # define XOFFSET(x) ((x) + device_origin_x)
00087 # define YSCALEREL(dy) ((dy) * user_scale_y)
00088 # define XSCALEREL(dx) ((dx) * user_scale_x)
00089 # define XSCALEBND(dx) (XSCALEREL(dx) + device_origin_x)
00090 # define YSCALEBND(dy) (YSCALEREL(dy) + device_origin_y)
00091 
00092 # define ASCALEREL(a) ((a) * ascale)
00093 
00094 # define PIE pie
00095 
00096 #define RESET_FONT 0x1
00097 #define RESET_COLOR 0x2
00098 
00099 static double pie = 0.0;
00100 
00101 #ifndef WXUNUSED
00102 # define WXUNUSED(x) x
00103 #endif
00104 
00105 #ifdef wx_xt
00106 # define WXXTUNUSED(c) /* empty */
00107 #else
00108 # define WXXTUNUSED(x) x
00109 #endif
00110 
00111 #define DEFAULT_PAPER "Letter 8 1/2 x 11 in"
00112 
00113 class wxCanvas;
00114 
00115 #ifdef wx_msw
00116 # include "wx_privt.h"
00117 #endif
00118 
00119 #include <math.h>
00120 #include <stdlib.h>
00121 #include <limits.h>
00122 
00123 static char *default_afm_path = NULL;
00124 
00125 Bool XPrinterDialog(wxWindow *parent);
00126 
00127 #ifdef wx_mac
00128 wxPrintPaperDatabase *wxThePrintPaperDatabase;
00129 #endif
00130 
00131 #ifndef wx_xt
00132 # define current_font font
00133 #else
00134 # define current_bk_mode current_text_bgmode
00135 # define current_text_foreground current_text_fg
00136 # define current_text_background current_text_bg
00137 #endif
00138 
00139 /**************************************************/
00140 
00141 wxPSStream::wxPSStream(char *file) {
00142   Scheme_Object *o;
00143   f_in = scheme_open_input_output_file(file, "post-script-dc%", &o);
00144   f = o;
00145   int_width = 0;
00146 }
00147  
00148 wxPSStream::~wxPSStream(void) {
00149   if (f_in) {
00150     scheme_close_input_port((Scheme_Object *)f_in);
00151     f_in = NULL;
00152   }
00153   if (f) {
00154     scheme_close_output_port((Scheme_Object *)f);
00155     f = NULL;
00156   }
00157 }
00158 
00159 int wxPSStream::good(void) {
00160   return !!f;
00161 }
00162 
00163 void wxPSStream::Out(char s) {
00164   char s2[2];
00165   s2[0] = s;
00166   s2[1] = 0;
00167   Out(s2);
00168 }
00169 
00170 void wxPSStream::Out(const char *s) {
00171   scheme_put_byte_string("post-script-dc%", (Scheme_Object *)f, s, 0, strlen(s), 0);
00172 }
00173 
00174 void wxPSStream::Out(int i) {
00175   Out((long)i);
00176 }
00177 
00178 void wxPSStream::Out(double n)
00179 {
00180   char buf[64];
00181 
00182   if ((double)(long)n == n) {
00183     Out((long)n);
00184     return;
00185   }
00186   sprintf(buf, "%f", n);
00187   Out(buf);
00188 }
00189 
00190 void wxPSStream::Out(long l)
00191 {
00192   char buf[64];
00193 
00194   if (int_width > 0) {
00195     char buffer[50];
00196     sprintf(buffer, "%% %d.%dld", int_width, int_width);
00197     sprintf(buf, buffer, l);
00198     int_width = 0;
00199   } else
00200     sprintf(buf, "%ld", l);
00201   Out(buf);
00202 }
00203 
00204 void wxPSStream::flush() {
00205   scheme_flush_output((Scheme_Object *)f);
00206 }
00207 
00208 long wxPSStream::tellp(void) {
00209   return scheme_set_file_position((Scheme_Object *)f, -1);
00210 }
00211  
00212 void wxPSStream::seekp(long pos) {
00213   scheme_set_file_position((Scheme_Object *)f, pos);
00214 }
00215 
00216 void wxPSStream::width(int w) {
00217   int_width = w;
00218 }
00219 
00220 long wxPSStream::read_at(long pos, char *buf, long amt) {
00221   scheme_set_file_position((Scheme_Object *)f_in, pos);
00222   return scheme_get_byte_string("post-script%", (Scheme_Object *)f_in,
00223                                 buf, 0, amt,
00224                                 0, 0, NULL);
00225 }
00226 
00227 
00228 /**************************************************/
00229 
00230 
00231 wxPostScriptDC::wxPostScriptDC (Bool interactive, wxWindow *parent, Bool usePaperBBox, Bool asEPS)
00232 {
00233   Create(interactive, parent, usePaperBBox, asEPS);
00234 }
00235 
00236 Bool wxPostScriptDC::Create(Bool interactive, wxWindow *parent, Bool usePaperBBox, Bool asEPS)
00237 {
00238   wxPrintSetupData *wxThePrintSetupData;
00239   char *paperType;
00240   wxPrintPaperType *paper;
00241 
00242   if (!pie)
00243     pie = 2 * asin((double)1.0);
00244 
00245   __type = wxTYPE_DC_POSTSCRIPT;
00246 #ifndef wx_xt
00247   wx_interactive = interactive;
00248 #endif
00249   current_font = wxNORMAL_FONT;
00250   device = wxDEVICE_EPS;
00251   clipping = NULL;
00252 
00253 #ifndef wx_xt
00254 # ifdef wx_mac
00255   logical_origin_x = 0;
00256   logical_origin_y = 0;
00257   logical_scale_x = 1.0;
00258   logical_scale_y = 1.0;
00259 # endif
00260 
00261   device_origin_x = 0;
00262   device_origin_y = 0;
00263 
00264   user_scale_x = 1.0;
00265   user_scale_y = 1.0;
00266 
00267   current_pen = NULL;
00268   current_brush = NULL;
00269   current_background_color = new WXGC_PTRS wxColour(wxWHITE);
00270 
00271   current_text_foreground = new WXGC_PTRS wxColour(wxBLACK);
00272 
00273   mapping_mode = MM_TEXT;
00274 #else
00275   current_pen = wxBLACK_PEN;
00276   current_pen->Lock(1);
00277   current_brush = wxWHITE_BRUSH;
00278   current_brush->Lock(1);
00279   current_background_color->CopyFrom(wxWHITE);
00280 #endif
00281 
00282   title = NULL;
00283 
00284   filename = NULL;
00285 
00286   pstream = NULL;
00287 
00288   min_x = 10000.0;
00289   min_y = 10000.0;
00290   max_x = -10000.0;
00291   max_y = -10000.0;
00292 
00293   clipx = -100000.0;
00294   clipy = -100000.0;
00295   clipw = 200000.0;
00296   cliph = 200000.0;
00297 
00298   as_eps = asEPS;
00299   ok = PrinterDialog(interactive, parent, usePaperBBox);
00300 
00301   /* We set these even if !ok, for use with text sizing: */
00302   wxThePrintSetupData = wxGetThePrintSetupData();
00303   level2ok = wxThePrintSetupData->GetLevel2();
00304   afm_path = wxThePrintSetupData->GetAFMPath();
00305 
00306   if (!ok)
00307     return FALSE;
00308 
00309   currentRed = 0;
00310   currentGreen = 0;
00311   currentBlue = 0;
00312 
00313   Colour = TRUE;
00314   
00315   paperType = wxThePrintSetupData->GetPaperName();
00316   if (!paperType)
00317     paperType = DEFAULT_PAPER;
00318 
00319   paper = wxThePrintPaperDatabase->FindPaperType(paperType);
00320   if (!paper)
00321     paper = wxThePrintPaperDatabase->FindPaperType(DEFAULT_PAPER);
00322   if (paper) {
00323     paper_w = (double)paper->widthPixels;
00324     paper_h = (double)paper->heightPixels;
00325   } else {
00326     paper_w = 1000;
00327     paper_h = 1000;
00328   }
00329 
00330   if (wxThePrintSetupData) {
00331     wxThePrintSetupData->GetPrinterTranslation(&paper_x, &paper_y);
00332     wxThePrintSetupData->GetPrinterScaling(&paper_x_scale, &paper_y_scale);
00333     if (wxThePrintSetupData->GetPrinterOrientation() == PS_LANDSCAPE)
00334       landscape = 1;
00335     else
00336       landscape = 0;
00337     wxThePrintSetupData->GetMargin(&paper_margin_x, &paper_margin_y);
00338   } else {
00339     paper_x = paper_y = 0;
00340     paper_x_scale = paper_y_scale = 1;
00341     paper_margin_x = paper_margin_y = 0;
00342     landscape = 0;
00343   }
00344 
00345   if (landscape) {
00346     double tmp;
00347 
00348     tmp = paper_w;
00349     paper_w = paper_h;
00350     paper_h = tmp;
00351   }
00352 
00353   paper_w -= (paper_margin_x * 2);
00354   paper_h -= (paper_margin_y * 2);
00355 
00356   paper_w /= paper_x_scale;
00357   if (paper_w <= 0)
00358     paper_w = 1;
00359   paper_h /= paper_y_scale;
00360   if (paper_h <= 0)
00361     paper_h = 1;
00362 
00363   anti_alias = 1;
00364 
00365   return ok;
00366 }
00367 
00368 wxPostScriptDC::~wxPostScriptDC (void)
00369 {
00370   if (current_brush) current_brush->Lock(-1);
00371   if (current_pen) current_pen->Lock(-1);
00372 
00373   if (pstream)
00374     DELETE_OBJ pstream;
00375 }
00376 
00377 Bool wxPostScriptDC::PrinterDialog(Bool interactive, wxWindow *parent, Bool usePaperBBox)
00378 {
00379   wxPrintSetupData *wxThePrintSetupData;
00380   char *s;
00381 
00382   if (interactive) {
00383     ok = XPrinterDialog(parent);
00384     if (!ok)
00385       return FALSE;
00386   } else
00387     ok = TRUE;
00388   
00389   wxThePrintSetupData = wxGetThePrintSetupData();
00390 
00391   mode = wxThePrintSetupData->GetPrinterMode();
00392   s = wxThePrintSetupData->GetPrintPreviewCommand();
00393   preview_cmd = copystring(s);
00394   s = wxThePrintSetupData->GetPrinterCommand();
00395   print_cmd = copystring(s);
00396   s = wxThePrintSetupData->GetPrinterOptions();
00397   print_opts = copystring(s);
00398 
00399   use_paper_bbox = usePaperBBox;
00400 
00401   if ((mode == PS_PREVIEW) || (mode == PS_PRINTER)) {
00402     // For PS_PRINTER action this depends on a Unix-style print spooler
00403     // since the wx_printer_file can be destroyed during a session
00404     char userId[256];
00405     char tmp[256];
00406     wxGetUserId (userId, sizeof (userId) / sizeof (char));
00407     strcpy(tmp, "/tmp/preview_");
00408     strcat(tmp, userId);
00409     strcat(tmp, ".ps");
00410     filename = copystring(tmp);
00411   } else if (mode == PS_FILE) {
00412     char *file;
00413     file = interactive ? (char *)NULL : wxThePrintSetupData->GetPrinterFile();
00414     if (!file) {
00415       char *dir = NULL;
00416       file = wxThePrintSetupData->GetPrinterFile();
00417       if (file) {
00418        dir = wxPathOnly(file);
00419        file = wxFileNameFromPath(file);
00420       }
00421       file = wxFileSelector("Save PostScript As", dir, file, "ps", NULL, wxSAVE, parent, -1, -1);
00422     }
00423     if (!file) {
00424       ok = FALSE;
00425       return FALSE;
00426     }
00427     filename = copystring(file);
00428     ok = TRUE;
00429   }
00430 
00431   return ok;
00432 }
00433 
00434 void wxPostScriptDC::SetClippingRect(double cx, double cy, double cw, double ch)
00435 {
00436   wxRegion *r;
00437 
00438   if (!pstream)
00439     return;
00440 
00441   r = new WXGC_PTRS wxRegion(this);
00442   r->SetRectangle(cx, cy, cw, ch);
00443 
00444   SetClippingRegion(r);
00445 }
00446 
00447 wxRegion *wxPostScriptDC::GetClippingRegion()
00448 {
00449   return clipping;
00450 }
00451 
00452 void wxPostScriptDC::SetClippingRegion(wxRegion *r)
00453 {
00454   if (!pstream)
00455     return;
00456   if (r && (r->GetDC() != this))
00457     return;
00458 
00459   if (r) {
00460     double x, y, w, h;
00461     r->BoundingBox(&x, &y, &w, &h);
00462     clipx = XSCALEBND(x);
00463     clipy = YSCALEBND(y);
00464     clipw = XSCALEREL(w);
00465     cliph = YSCALEREL(h);
00466   } else {
00467     clipx = -100000.0;
00468     clipy = -100000.0;
00469     clipw = 200000.0;
00470     cliph = 200000.0;
00471   }
00472 
00473   if (clipping) {
00474     --clipping->locked;
00475     clipping = NULL;
00476     pstream->Out("initclip\n");
00477   }
00478 
00479   if (r) {
00480     r->InstallPS(this, pstream);
00481 
00482     clipping = r;
00483     clipping->locked++;
00484   }
00485 }
00486 
00487 void wxPostScriptDC::CalcBoundingBoxClip(double x, double y)
00488 {
00489   if (x < clipx)
00490     x = clipx;
00491   else if (x >= (clipx + clipw))
00492     x = clipx + clipw;
00493   
00494   if (y < clipy)
00495     y = clipy;
00496   else if (y >= (clipy + cliph))
00497     y = clipy + cliph;
00498 
00499   if (x < min_x) min_x = x;
00500   if (y < min_y) min_y = y;
00501   if (x > max_x) max_x = x;
00502   if (y > max_y) max_y = y;
00503 }
00504 
00505 void wxPostScriptDC::SetAntiAlias(int mode)
00506 {
00507   /* Don't change */
00508 }
00509 
00510 void wxPostScriptDC::Clear(void)
00511 {
00512   unsigned char red, blue, green;
00513 
00514   if (!pstream)
00515     return;
00516 
00517   red = current_background_color->Red();
00518   blue = current_background_color->Blue();
00519   green = current_background_color->Green();
00520 
00521   {
00522     double redPS = (double) (((int) red) / 255.0);
00523     double bluePS = (double) (((int) blue) / 255.0);
00524     double greenPS = (double) (((int) green) / 255.0);
00525     
00526     /* Fill with current background */
00527     pstream->Out("gsave newpath\n");
00528     pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n");
00529     pstream->Out(0); pstream->Out(" "); pstream->Out(0); pstream->Out(" moveto\n");
00530     pstream->Out(0); pstream->Out(" "); pstream->Out(paper_h); pstream->Out(" lineto\n");
00531     pstream->Out(paper_w); pstream->Out(" "); pstream->Out(paper_h); pstream->Out(" lineto\n");
00532     pstream->Out(paper_w); pstream->Out(" "); pstream->Out(0); pstream->Out(" lineto\n");
00533     pstream->Out("closepath\n");
00534     pstream->Out("fill grestore\n");
00535   }
00536 }
00537 
00538 Bool wxPostScriptDC::GetPixel(double WXUNUSED(x), double WXUNUSED(y), wxColour * WXUNUSED(col))
00539 {
00540   return FALSE;
00541 }
00542 
00543 void wxPostScriptDC::DrawLine (double x1, double y1, double x2, double y2)
00544 {
00545   if (!pstream)
00546     return;
00547   if (current_pen)
00548     SetPen (current_pen);
00549   pstream->Out("newpath\n");
00550   pstream->Out(XSCALE(x1)); pstream->Out(" "); pstream->Out(YSCALE (y1)); pstream->Out(" moveto\n");
00551   pstream->Out(XSCALE(x2)); pstream->Out(" "); pstream->Out(YSCALE (y2)); pstream->Out(" lineto\n");
00552   pstream->Out("stroke\n");
00553   
00554   {
00555     /* Need to make bounding box wide enough to show the pen.
00556        (Part of the reason for this is to avoid zero-sized boounding boxes.) */
00557     double width;
00558 
00559     if (current_pen) {
00560       width = current_pen->GetWidthF();
00561       width /= 2;
00562     } else
00563       width = 0;
00564 
00565     if (!width) width = 0.01;
00566 
00567     if (x1 == x2) {
00568       CalcBoundingBoxClip(XSCALEBND(x1 - width), YSCALEBND(y1));
00569       CalcBoundingBoxClip(XSCALEBND(x2 + width), YSCALEBND(y2));
00570     } else if (y1 == y2) {
00571       CalcBoundingBoxClip(XSCALEBND(x1), YSCALEBND(y1 - width));
00572       CalcBoundingBoxClip(XSCALEBND(x2), YSCALEBND(y2 + width));
00573     } else {
00574       CalcBoundingBoxClip(XSCALEBND(x1 - width), YSCALEBND(y1 - width));
00575       CalcBoundingBoxClip(XSCALEBND(x2 + width), YSCALEBND(y2 + width));
00576     }
00577   }
00578 }
00579 
00580 void wxPostScriptDC::DrawArc (double x, double y, double w, double h, double start, double end)
00581 {
00582   if (!pstream)
00583     return;
00584 
00585   if (start != end) {
00586     double a1, a2, radius, xscale;
00587 
00588     /* Before we scale: */
00589     CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y));
00590     CalcBoundingBoxClip(XSCALEBND(x + w), YSCALEBND(y + h));
00591 
00592     x = XSCALE(x);
00593     y = YSCALE(y);
00594     w = XSCALEREL(w);
00595     h = YSCALEREL(h);
00596 
00597     radius = (h / 2);
00598     xscale = (w / h);
00599 
00600     a1 = start * (180 / pie);
00601     a2 = end * (180 / pie);
00602 
00603     pstream->Out("gsave\n");
00604     pstream->Out((x + w/2)); pstream->Out(" "); 
00605     pstream->Out((y - h/2)); pstream->Out(" translate\n");
00606     pstream->Out(xscale); pstream->Out(" "); pstream->Out(1); pstream->Out(" scale\n");
00607 
00608     if (current_brush && current_brush->GetStyle () != wxTRANSPARENT) {
00609       SetBrush(current_brush);
00610       
00611       pstream->Out("newpath\n");
00612       pstream->Out(0); pstream->Out(" "); 
00613       pstream->Out(0); pstream->Out(" moveto\n");
00614       pstream->Out("0 0 "); pstream->Out(radius); pstream->Out(" "); pstream->Out(a1); 
00615       pstream->Out(" "); pstream->Out(a2); pstream->Out(" arc\n");
00616 
00617       pstream->Out("closepath\n");
00618 
00619       pstream->Out("fill\n");
00620     }
00621     if (current_pen && current_pen->GetStyle () != wxTRANSPARENT) {
00622       SetPen(current_pen);
00623 
00624       pstream->Out("newpath\n");
00625       pstream->Out("0 0 "); pstream->Out(radius); pstream->Out(" ");
00626       pstream->Out(a1); pstream->Out(" "); pstream->Out(a2); pstream->Out(" arc\n");
00627       pstream->Out("stroke\n");
00628     }
00629 
00630     pstream->Out("grestore\n");
00631     resetFont |= RESET_COLOR;
00632   }
00633 }
00634 
00635 void wxPostScriptDC::DrawPoint (double x, double y)
00636 {
00637   if (!pstream)
00638     return;
00639   if (current_pen)
00640     SetPen (current_pen);
00641   pstream->Out("newpath\n");
00642   pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" moveto\n");
00643   pstream->Out(XSCALE(x+1)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" lineto\n");
00644   pstream->Out("stroke\n");
00645   CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y));
00646 }
00647 
00648 void wxPostScriptDC::DrawSpline(double x1, double y1, double x2, double y2, double x3, double y3)
00649 {
00650   double x21, y21, x22, y22;
00651   double xm1, ym1, xm2, ym2;
00652 
00653   if (!pstream)
00654     return;
00655 
00656   if (current_pen)
00657     SetPen (current_pen);
00658 
00659   pstream->Out("newpath\n");
00660 
00661   pstream->Out(XSCALE(x1)); pstream->Out(" "); pstream->Out(YSCALE(y1)); pstream->Out(" moveto ");
00662 
00663   x21 = (x1 + x2) / 2;
00664   y21 = (y1 + y2) / 2;
00665 
00666   pstream->Out(XSCALE(x21)); pstream->Out(" "); pstream->Out(YSCALE(y21)); pstream->Out(" lineto\n");
00667 
00668   x22 = (x2 + x3) / 2;
00669   y22 = (y2 + y3) / 2;
00670   
00671   xm1 = (x21 + x2) / 2;
00672   ym1 = (y21 + y2) / 2;
00673 
00674   xm2 = (x2 + x22) / 2;
00675   ym2 = (y2 + y22) / 2;
00676 
00677   pstream->Out(XSCALE(xm1)); pstream->Out(" "); pstream->Out(YSCALE(ym1)); pstream->Out(" "); 
00678 
00679   pstream->Out(XSCALE(xm2)); pstream->Out(" "); pstream->Out(YSCALE(ym2)); pstream->Out(" "); 
00680 
00681   pstream->Out(XSCALE(x22)); pstream->Out(" "); pstream->Out(YSCALE(y22)); pstream->Out(" curveto\n");
00682 
00683   pstream->Out(XSCALE(x3)); pstream->Out(" "); pstream->Out(YSCALE(y3)); pstream->Out(" lineto\n");
00684 
00685   pstream->Out("stroke\n");
00686 
00687   CalcBoundingBoxClip(XSCALEBND(x1), YSCALEBND(y1));
00688   CalcBoundingBoxClip(XSCALEBND(x2), YSCALEBND(y2));
00689   CalcBoundingBoxClip(XSCALEBND(x3), YSCALEBND(y3));
00690 }
00691 
00692 void wxPostScriptDC::DrawPolygon (int n, wxPoint points[], double xoffset, double yoffset, int fillStyle)
00693 {
00694   if (!pstream)
00695     return;
00696   if (n > 0)
00697     {
00698       if (current_brush && current_brush->GetStyle () != wxTRANSPARENT)
00699        {
00700          int i;
00701          double xx, yy;
00702 
00703          SetBrush (current_brush);
00704          pstream->Out("newpath\n");
00705 
00706          xx = points[0].x + xoffset;
00707          yy = (points[0].y + yoffset);
00708          pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" moveto\n");
00709          CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy));
00710 
00711          for (i = 1; i < n; i++)
00712            {
00713              xx = points[i].x + xoffset;
00714              yy = (points[i].y + yoffset);
00715              pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" lineto\n");
00716              CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy));
00717            }
00718          pstream->Out(((fillStyle == wxODDEVEN_RULE) ? "eofill\n" : "fill\n"));
00719        }
00720 
00721       if (current_pen && current_pen->GetStyle () != wxTRANSPARENT)
00722        {
00723          int i;
00724          double xx, yy;
00725 
00726          SetPen (current_pen);
00727          pstream->Out("newpath\n");
00728 
00729          xx = points[0].x + xoffset;
00730          yy = (points[0].y + yoffset);
00731          pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" moveto\n");
00732          CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy));
00733 
00734          for (i = 1; i < n; i++)
00735            {
00736              xx = points[i].x + xoffset;
00737              yy = (points[i].y + yoffset);
00738              pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" lineto\n");
00739              CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy));
00740            }
00741 
00742          // Close the polygon
00743          pstream->Out(" closepath\n");
00744 
00745          // Output the line
00746          pstream->Out("stroke\n");
00747        }
00748     }
00749 }
00750 
00751 void wxPostScriptDC::DrawPath(wxPath *p, double xoff, double yoff, int fillStyle)
00752 {
00753   int did = 0;
00754 
00755   if (!pstream)
00756     return;
00757   
00758   if (current_brush && current_brush->GetStyle () != wxTRANSPARENT) {
00759     SetBrush (current_brush);
00760     pstream->Out("newpath\n");
00761     p->InstallPS(this, pstream, xoff, yoff);
00762     pstream->Out(((fillStyle == wxODDEVEN_RULE) ? "eofill\n" : "fill\n"));
00763     did = 1;
00764   }
00765 
00766   if (current_pen && current_pen->GetStyle () != wxTRANSPARENT) {
00767     SetPen (current_pen);
00768     pstream->Out("newpath\n");
00769     p->InstallPS(this, pstream, xoff, yoff);
00770     pstream->Out("stroke\n");
00771     did = 1;
00772   }
00773 
00774   if (did) {
00775     double x1, x2, y1, y2;
00776     p->BoundingBox(&x1, &y1, &x2, &y2);
00777     x1 += xoff; 
00778     x2 += xoff;
00779     y1 += yoff; 
00780     y2 += yoff;
00781     CalcBoundingBoxClip(XSCALEBND(x1), YSCALEBND(y1));
00782     CalcBoundingBoxClip(XSCALEBND(x2), YSCALEBND(y2));
00783   }
00784 }
00785 
00786 
00787 void wxPostScriptDC::DrawLines (int n, wxPoint points[], double xoffset, double yoffset)
00788 {
00789   if (!pstream)
00790     return;
00791 
00792   if (n > 0 && current_pen && (current_pen->GetStyle () != wxTRANSPARENT)) {
00793     int i;
00794     double xx, yy;
00795 
00796     SetPen(current_pen);
00797     
00798     pstream->Out("newpath\n");
00799     
00800     xx = points[0].x + xoffset;
00801     yy = (points[0].y + yoffset);
00802     pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" moveto\n");
00803     CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy));
00804     
00805     for (i = 1; i < n; i++)
00806       {
00807        xx = points[i].x + xoffset;
00808        yy = (points[i].y + yoffset);
00809        pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" lineto\n");
00810        CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy));
00811       }
00812     pstream->Out("stroke\n");
00813   }
00814 }
00815 
00816 void wxPostScriptDC::DrawRectangle (double x, double y, double width, double height)
00817 {
00818   if (!pstream)
00819     return;
00820   if (current_brush && current_brush->GetStyle () != wxTRANSPARENT)
00821     {
00822       SetBrush (current_brush);
00823 
00824       pstream->Out("newpath\n");
00825       pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" moveto\n");
00826       pstream->Out(XSCALE(x + width)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" lineto\n");
00827       pstream->Out(XSCALE(x + width)); pstream->Out(" "); pstream->Out(YSCALE (y + height)); pstream->Out(" lineto\n");
00828       pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y + height)); pstream->Out(" lineto\n");
00829       pstream->Out("closepath\n");
00830       pstream->Out("fill\n");
00831 
00832       CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y));
00833       CalcBoundingBoxClip(XSCALEBND(x + width), YSCALEBND(y + height));
00834     }
00835   if (current_pen && current_pen->GetStyle () != wxTRANSPARENT)
00836     {
00837       double pw;
00838 
00839       SetPen (current_pen);
00840 
00841       pstream->Out("newpath\n");
00842       pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" moveto\n");
00843       pstream->Out(XSCALE(x + width)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" lineto\n");
00844       pstream->Out(XSCALE(x + width)); pstream->Out(" "); pstream->Out(YSCALE (y + height)); pstream->Out(" lineto\n");
00845       pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y + height)); pstream->Out(" lineto\n");
00846       pstream->Out("closepath\n");
00847       pstream->Out("stroke\n");
00848 
00849       if (current_pen) {
00850         pw = current_pen->GetWidthF();
00851         pw /= 2;
00852       } else
00853         pw = 0;
00854 
00855       CalcBoundingBoxClip(XSCALEBND(x - pw), YSCALEBND(y - pw));
00856       CalcBoundingBoxClip(XSCALEBND(x + width + pw),  YSCALEBND(y + height + pw));
00857     }
00858 }
00859 
00860 void wxPostScriptDC::DrawRoundedRectangle (double x, double y, double width, double height, double radius)
00861 {
00862   double ascale;
00863 
00864   if (!pstream)
00865     return;
00866 
00867   if (radius < 0.0)
00868     {
00869       // Now, a negative radius is interpreted to mean
00870       // 'the proportion of the smallest X or Y dimension'
00871       double smallest = 0.0;
00872       if (width < height)
00873        smallest = width;
00874       else
00875        smallest = height;
00876       radius = (double) (-radius * smallest);
00877     }
00878 
00879   ascale = (user_scale_x < user_scale_y) ? user_scale_x : user_scale_y;
00880 
00881   if (current_brush && current_brush->GetStyle () != wxTRANSPARENT)
00882     {
00883       SetBrush (current_brush);
00884       // Draw rectangle anticlockwise
00885       pstream->Out("newpath\n");
00886 
00887       pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" "); 
00888       pstream->Out(YSCALE(y)); pstream->Out(" moveto\n");
00889 
00890       pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" ");
00891       pstream->Out(YSCALE(y) - ASCALEREL(radius)); pstream->Out(" ");
00892       pstream->Out(ASCALEREL(radius)); pstream->Out(" 90 180 arc\n");
00893 
00894       pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" ");
00895       pstream->Out(YSCALE(y + height) + ASCALEREL(radius)); pstream->Out(" ");
00896       pstream->Out(ASCALEREL(radius)); pstream->Out(" 180 270 arc\n");
00897 
00898       pstream->Out(XSCALE(x + width) - ASCALEREL(radius)); pstream->Out(" ");
00899       pstream->Out(YSCALE(y + height) + ASCALEREL(radius)); pstream->Out(" ");
00900       pstream->Out(ASCALEREL(radius)); pstream->Out(" 270 0 arc\n");
00901 
00902       pstream->Out(XSCALE(x + width) - ASCALEREL(radius)); pstream->Out(" ");
00903       pstream->Out(YSCALE(y) - ASCALEREL(radius)); pstream->Out(" ");
00904       pstream->Out(ASCALEREL(radius)); pstream->Out(" 0 90 arc\n");
00905 
00906       pstream->Out("closepath\n");
00907 
00908       pstream->Out("fill\n");
00909 
00910       CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y));
00911       CalcBoundingBoxClip(XSCALEBND(x + width), YSCALEBND(y + height));
00912     }
00913   if (current_pen && current_pen->GetStyle () != wxTRANSPARENT)
00914     {
00915       SetPen (current_pen);
00916       // Draw rectangle anticlockwise
00917       pstream->Out("newpath\n");
00918 
00919       pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" "); 
00920       pstream->Out(YSCALE(y)); pstream->Out(" moveto\n");
00921 
00922       pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" ");
00923       pstream->Out(YSCALE(y) - ASCALEREL(radius)); pstream->Out(" "); 
00924       pstream->Out(ASCALEREL(radius)); pstream->Out(" 90 180 arc\n");
00925 
00926       pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" ");
00927       pstream->Out(YSCALE(y + height) + ASCALEREL(radius)); pstream->Out(" "); 
00928       pstream->Out(ASCALEREL(radius)); pstream->Out(" 180 270 arc\n");
00929 
00930       pstream->Out(XSCALE(x + width) - ASCALEREL(radius)); pstream->Out(" ");
00931       pstream->Out(YSCALE(y + height) + ASCALEREL(radius)); pstream->Out(" "); 
00932       pstream->Out(ASCALEREL(radius)); pstream->Out(" 270 0 arc\n");
00933 
00934       pstream->Out(XSCALE(x + width) - ASCALEREL(radius)); pstream->Out(" ");
00935       pstream->Out(YSCALE(y) - ASCALEREL(radius)); pstream->Out(" "); 
00936       pstream->Out(ASCALEREL(radius)); pstream->Out(" 0 90 arc\n");
00937 
00938       pstream->Out("closepath\n");
00939 
00940       pstream->Out("stroke\n");
00941 
00942       {
00943         double pw;
00944 
00945         if (current_pen) {
00946           pw = current_pen->GetWidthF();
00947           pw /= 2;
00948         } else
00949           pw = 0;
00950         
00951         CalcBoundingBoxClip(XSCALEBND(x - pw), YSCALEBND(y - pw));
00952         CalcBoundingBoxClip(XSCALEBND(x + width + pw),  YSCALEBND(y + height + pw));
00953       }
00954     }
00955 }
00956 
00957 void wxPostScriptDC::DrawEllipse (double x, double y, double width, double height)
00958 {
00959   if (!pstream)
00960     return;
00961   if (current_brush && current_brush->GetStyle () != wxTRANSPARENT)
00962     {
00963       SetBrush (current_brush);
00964 
00965       pstream->Out("newpath\n");
00966       pstream->Out(XSCALE(x + width / 2)); pstream->Out(" "); pstream->Out(YSCALE(y + height / 2)); pstream->Out(" ");
00967       pstream->Out(XSCALEREL(width / 2)); pstream->Out(" "); pstream->Out(YSCALEREL(height / 2)); pstream->Out(" 0 360 ellipse\n");
00968       pstream->Out("fill\n");
00969 
00970       CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y));
00971       CalcBoundingBoxClip(XSCALEBND(x + width), YSCALEBND(y + height));
00972     }
00973   if (current_pen && current_pen->GetStyle () != wxTRANSPARENT)
00974     {
00975       SetPen (current_pen);
00976 
00977       pstream->Out("newpath\n");
00978       pstream->Out(XSCALE(x + width / 2)); pstream->Out(" "); pstream->Out(YSCALE(y + height / 2)); pstream->Out(" ");
00979       pstream->Out(XSCALEREL(width / 2)); pstream->Out(" "); pstream->Out(YSCALEREL(height / 2)); pstream->Out(" 0 360 ellipse\n");
00980       pstream->Out("stroke\n");
00981       
00982       {
00983         double pw;
00984 
00985         if (current_pen) {
00986           pw = current_pen->GetWidthF();
00987           pw /= 2;
00988         } else
00989           pw = 0;
00990         
00991         CalcBoundingBoxClip(XSCALEBND(x - pw), YSCALEBND(y - pw));
00992         CalcBoundingBoxClip(XSCALEBND(x + width + pw),  YSCALEBND(y + height + pw));
00993       }
00994     }
00995 }
00996 
00997 void wxPostScriptDC::SetFont (wxFont * the_font)
00998 {
00999   char *name;
01000   int family, style, weight, size;
01001 
01002   if (!pstream)
01003     return;
01004   if ((current_font == the_font) && !(resetFont & RESET_FONT))
01005     return;
01006 
01007   resetFont -= (resetFont & RESET_FONT);
01008 
01009   current_font = the_font;
01010   family = current_font->GetFontId();
01011   style = current_font->GetStyle();
01012   weight = current_font->GetWeight();
01013 
01014   name = wxTheFontNameDirectory->GetPostScriptName(family, weight, style);
01015   if (!name)
01016     name = "Times-Roman";
01017 
01018   size = current_font->GetPointSize();
01019 
01020   next_font_name = name;
01021   next_font_size = size;
01022 }
01023 
01024 static void set_pattern(wxPostScriptDC *dc, wxPSStream *pstream, wxBitmap *bm, int rop, wxColour *col)
01025 {
01026   int width, height;
01027 
01028   width = bm->GetWidth();
01029   height = bm->GetHeight();
01030 
01031   pstream->Out("8 dict\n");
01032   pstream->Out("dup\n");
01033   pstream->Out("begin\n");
01034   pstream->Out(" /PatternType 1 def\n");
01035   pstream->Out(" /PaintType 1 def\n");
01036   pstream->Out(" /TilingType 1 def\n");
01037   pstream->Out(" /BBox [ 0 0 "); pstream->Out(width); pstream->Out(" "); pstream->Out(height); pstream->Out(" ] def\n");
01038   pstream->Out(" /XStep "); pstream->Out(width); pstream->Out(" def\n");
01039   pstream->Out(" /YStep "); pstream->Out(height); pstream->Out(" def\n");
01040 
01041   dc->Blit(0, 0, width, height, bm, 0, 0, -rop - 1, col);
01042 
01043   pstream->Out("end\n");
01044   pstream->Out(" matrix makepattern setpattern\n");
01045 }
01046 
01047 static char *dotted = "[2 5] 2";
01048 static char *short_dashed = "[4 4] 2";
01049 static char *long_dashed = "[4 8] 2";
01050 static char *dotted_dashed = "[6 6 2 6] 4";
01051 
01052 void wxPostScriptDC::SetPen (wxPen * pen)
01053 {
01054   wxPen *oldPen = current_pen;
01055   char *psdash = NULL;
01056   unsigned char red, blue, green;
01057   int val;
01058   double width;
01059 
01060   if (!pstream)
01061     return;
01062 
01063   if (current_pen) current_pen->Lock(-1);
01064   if (pen) pen->Lock(1);
01065 
01066   if ((current_pen = pen) == NULL)
01067     return;                 /* NIL */
01068 
01069   // Line width
01070   width = pen->GetWidthF();
01071   pstream->Out(XSCALEREL(width));
01072   pstream->Out(" setlinewidth\n");
01073 
01074   if (level2ok) {
01075     wxBitmap *stipple;
01076     stipple = pen->GetStipple();
01077     if (stipple && stipple->Ok()) {
01078       int ps;
01079       wxColour *pc;
01080       ps = pen->GetStyle();
01081       pc = pen->GetColour();
01082       set_pattern(this, pstream, stipple, ps, pc);
01083       resetFont |= RESET_COLOR;
01084       return;
01085     }
01086   }
01087 
01088   switch (pen->GetStyle ())
01089     {
01090     case wxDOT:
01091       psdash = dotted;
01092       break;
01093     case wxSHORT_DASH:
01094       psdash = short_dashed;
01095       break;
01096     case wxLONG_DASH:
01097       psdash = long_dashed;
01098       break;
01099     case wxDOT_DASH:
01100       psdash = dotted_dashed;
01101       break;
01102     case wxSOLID:
01103     case wxTRANSPARENT:
01104     default:
01105       psdash = "[] 0";
01106       break;
01107     }
01108   if (oldPen != pen) {
01109     pstream->Out(psdash); pstream->Out(" setdash\n");
01110   }
01111 
01112   switch (pen->GetCap()) {
01113   case wxCAP_ROUND:
01114     val = 1;
01115     break;
01116   case wxCAP_PROJECTING:
01117     val = 2;
01118     break;
01119   default:
01120   case wxCAP_BUTT:
01121     val = 0;
01122     break;
01123   }
01124   pstream->Out(val);
01125   pstream->Out(" setlinecap\n");
01126 
01127   switch (pen->GetJoin()) {
01128   case wxJOIN_ROUND:
01129     val = 1;
01130     break;
01131   case wxJOIN_BEVEL:
01132     val = 2;
01133     break;
01134   default:
01135   case wxJOIN_MITER:
01136     val = 0;
01137     break;
01138   }
01139   pstream->Out(val);
01140   pstream->Out(" setlinejoin\n");
01141 
01142   // Line colour
01143   {
01144     wxColour *pc;
01145     pc = pen->GetColour();
01146     red = pc->Red();
01147     blue = pc->Blue();
01148     green = pc->Green();
01149   }
01150 
01151   if (!Colour)
01152     {
01153       // Anything not white is black
01154       if (!(red == (unsigned char) 255 && blue == (unsigned char) 255
01155            && green == (unsigned char) 255))
01156        {
01157          red = (unsigned char) 0;
01158          green = (unsigned char) 0;
01159          blue = (unsigned char) 0;
01160        }
01161     }
01162 
01163   if (!(red == currentRed && green == currentGreen && blue == currentBlue)
01164       || (resetFont & RESET_COLOR)) {
01165     double redPS = (double) (((int) red) / 255.0);
01166     double bluePS = (double) (((int) blue) / 255.0);
01167     double greenPS = (double) (((int) green) / 255.0);
01168 
01169     pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); 
01170     pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n");
01171     
01172     currentRed = red;
01173     currentBlue = blue;
01174     currentGreen = green;
01175     resetFont -= (resetFont & RESET_COLOR);
01176   }
01177 }
01178 
01179 static char *ps_brush_hatch[] = { " 0 0 moveto 8 8",
01180                               " 0 0 moveto 8 8 lineto closepath stroke 8 0 moveto 0 8",
01181                               " 8 0 moveto 0 8",
01182                               " 0 4 moveto 8 4 lineto closepath stroke 4 0 moveto 4 8",
01183                               " 0 4 moveto 8 4",
01184                               " 4 0 moveto 4 8",
01185                               " 0 0 moveto 0.1 0.1" };
01186 
01187 void wxPostScriptDC::SetBrush(wxBrush * brush)
01188 {
01189   unsigned char red, blue, green;
01190   int hatch_id;
01191   char *hatch_size;
01192   double redPS, bluePS, greenPS;
01193 
01194   if (!pstream)
01195     return;
01196 
01197   if (current_brush) current_brush->Lock(-1);
01198   if (brush) brush->Lock(1);
01199 
01200   if ((current_brush = brush) == NULL)
01201     return; 
01202 
01203   if (level2ok) {
01204     wxBitmap *stipple;
01205     stipple = brush->GetStipple();
01206     if (stipple && stipple->Ok()) {
01207       int bs;
01208       wxColour *bc;
01209       bs = brush->GetStyle();
01210       bc = brush->GetColour();
01211       set_pattern(this, pstream, stipple, bs, bc);
01212       resetFont |= RESET_COLOR;
01213       return;
01214     }
01215   }
01216 
01217   // Brush colour
01218   {
01219     wxColour *bc;
01220     bc = brush->GetColour(); 
01221     red = bc->Red();
01222     blue = bc->Blue();
01223     green = bc->Green();
01224   }
01225 
01226   if (!Colour) {
01227     // Anything not black is white
01228     if (!(red == (unsigned char) 0 && blue == (unsigned char) 0
01229          && green == (unsigned char) 0)) {
01230       red = (unsigned char) 255;
01231       green = (unsigned char) 255;
01232       blue = (unsigned char) 255;
01233     }
01234   }
01235 
01236   hatch_id = -1;
01237   hatch_size = "8";
01238   switch (brush->GetStyle()) {
01239   case wxBDIAGONAL_HATCH:
01240     hatch_id = 0;
01241     break;
01242   case wxCROSSDIAG_HATCH:
01243     hatch_id = 1;
01244     break;
01245   case wxFDIAGONAL_HATCH:
01246     hatch_id = 2;
01247     break;
01248   case wxCROSS_HATCH:
01249     hatch_id = 3;
01250     break;
01251   case wxHORIZONTAL_HATCH:
01252     hatch_id = 4;
01253     break;
01254   case wxVERTICAL_HATCH:
01255     hatch_id = 5;
01256     break;
01257   case wxCOLOR:
01258     hatch_id = 6;
01259     hatch_size = "0.3";
01260     break;
01261   }
01262 
01263   redPS = (double) (((int) red) / 255.0);
01264   bluePS = (double) (((int) blue) / 255.0);
01265   greenPS = (double) (((int) green) / 255.0);
01266 
01267   if (hatch_id > -1) {
01268     pstream->Out("7 dict\n");
01269     pstream->Out("dup\n");
01270     pstream->Out("begin\n");
01271     pstream->Out(" /PatternType 1 def\n");
01272     pstream->Out(" /PaintType 1 def\n");
01273     pstream->Out(" /TilingType 1 def\n");
01274     pstream->Out(" /BBox [ 0 0 ");
01275     pstream->Out(hatch_size);
01276     pstream->Out(" ");
01277     pstream->Out(hatch_size);
01278     pstream->Out(" ] def\n");
01279     pstream->Out(" /XStep ");
01280     pstream->Out(hatch_size);
01281     pstream->Out(" def\n");
01282     pstream->Out(" /YStep ");
01283     pstream->Out(hatch_size);
01284     pstream->Out(" def\n");
01285     pstream->Out(" /PaintProc { begin gsave \n");
01286 
01287     pstream->Out(" 0.05 setlinewidth\n");
01288     pstream->Out(" [] 0 setdash\n");
01289     pstream->Out(" "); pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); 
01290     pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n");
01291 
01292     pstream->Out(" "); pstream->Out(ps_brush_hatch[hatch_id]); pstream->Out(" lineto closepath stroke \n");
01293     
01294     pstream->Out("grestore\n } def \n");
01295     
01296     pstream->Out("end\n"); pstream->Out(" matrix makepattern setpattern\n");
01297 
01298     resetFont |= RESET_COLOR;
01299 
01300     return;
01301   }
01302 
01303   if (!(red == currentRed && green == currentGreen && blue == currentBlue)
01304       || (resetFont & RESET_COLOR)) {
01305     pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); 
01306     pstream->Out(bluePS); pstream->Out(" setrgbcolor\n");
01307     currentRed = red;
01308     currentBlue = blue;
01309     currentGreen = green;
01310     resetFont -= (resetFont & RESET_COLOR);
01311   }
01312 }
01313 
01314 void wxPostScriptDC::DrawText(DRAW_TEXT_CONST char *text, double x, double y,
01315                            Bool combine, Bool use16, int dt, double angle)
01316 {
01317   double tw, th;
01318   const char *name;
01319   int sym_map;
01320 
01321   if (!pstream)
01322     return;
01323   if (current_font)
01324     SetFont (current_font);
01325 
01326   GetTextExtent(text, &tw, &th, NULL, NULL, NULL, combine, use16, dt);
01327 
01328   if (current_bk_mode == wxSOLID) {
01329     unsigned char red, blue, green;
01330     
01331     red = current_text_background->Red();
01332     blue = current_text_background->Blue();
01333     green = current_text_background->Green();
01334     
01335     {
01336       double redPS = (double) (((int) red) / 255.0);
01337       double bluePS = (double) (((int) blue) / 255.0);
01338       double greenPS = (double) (((int) green) / 255.0);
01339       
01340       pstream->Out("gsave newpath\n");
01341       pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); 
01342       pstream->Out(bluePS); pstream->Out(" setrgbcolor\n");
01343       pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" moveto\n");
01344       pstream->Out(XSCALE(x + tw)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" lineto\n");
01345       pstream->Out(XSCALE(x + tw)); pstream->Out(" "); pstream->Out(YSCALE (y + th)); pstream->Out(" lineto\n");
01346       pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y + th)); pstream->Out(" lineto\n");
01347       pstream->Out("closepath\n");
01348       pstream->Out("fill grestore\n");
01349     }
01350   }
01351 
01352   if (current_text_foreground->Ok()) {
01353     unsigned char red, blue, green;
01354 
01355     red = current_text_foreground->Red();
01356     blue = current_text_foreground->Blue();
01357     green = current_text_foreground->Green();
01358     
01359     if (!Colour) {
01360       // Anything not white is black
01361       if (!(red == (unsigned char) 255 && blue == (unsigned char) 255
01362            && green == (unsigned char) 255))
01363        {
01364          red = (unsigned char) 0;
01365          green = (unsigned char) 0;
01366          blue = (unsigned char) 0;
01367        }
01368     }
01369     if (!(red == currentRed && green == currentGreen && blue == currentBlue)
01370        || (resetFont & RESET_COLOR)) {
01371       double redPS = (double) (((int) red) / 255.0);
01372       double bluePS = (double) (((int) blue) / 255.0);
01373       double greenPS = (double) (((int) green) / 255.0);
01374       pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); 
01375       pstream->Out(bluePS); pstream->Out(" setrgbcolor\n");
01376       
01377       currentRed = red;
01378       currentBlue = blue;
01379       currentGreen = green;
01380       resetFont -= (resetFont & RESET_COLOR);
01381     }
01382   }
01383   
01384   if (next_font_name) {
01385     if (!current_font_name
01386        || (next_font_size != current_font_size)
01387        || strcmp(next_font_name, current_font_name)) {
01388       char *fn;
01389       pstream->Out("/"); fn = wxPostScriptFixupFontName(next_font_name); pstream->Out(fn); pstream->Out(" findfont\n");
01390       pstream->Out(next_font_size); pstream->Out(" scalefont setfont\n");
01391       
01392       used_fonts = wxPostScriptRecordFont(fn, used_fonts);
01393 
01394       current_font_size = next_font_size;
01395       current_font_name = next_font_name;
01396     }
01397     name = next_font_name;
01398     next_font_name = NULL;
01399   } else {
01400     int family, style, weight;
01401     if (current_font) {
01402       family = current_font->GetFontId();
01403       style = current_font->GetStyle();
01404       weight = current_font->GetWeight();
01405     } else {
01406       family = wxDEFAULT;
01407       style = wxNORMAL;
01408       weight = wxNORMAL;
01409     }
01410     
01411     name = wxTheFontNameDirectory->GetPostScriptName(family, weight, style);
01412     if (!name)
01413       name = "Times-Roman";
01414   }
01415 
01416   if (angle != 0.0) {
01417     pstream->Out("gsave\n");
01418   }
01419 
01420   if (angle != 0.0) {
01421     pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE(y)); 
01422     pstream->Out(" translate\n");
01423     if ((user_scale_x != 1) || (user_scale_y != 1)) {
01424       pstream->Out(user_scale_x); pstream->Out(" "); pstream->Out(user_scale_y); pstream->Out(" scale\n");
01425     }
01426     pstream->Out(angle * 180 / pie);
01427     pstream->Out(" rotate 0 0 moveto\n"); 
01428   } else {
01429     pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE(y)); 
01430     pstream->Out(" moveto\n");
01431     if ((user_scale_x != 1) || (user_scale_y != 1)) {
01432       pstream->Out("gsave\n");
01433       pstream->Out(user_scale_x); pstream->Out(" "); pstream->Out(user_scale_y); pstream->Out(" scale\n");
01434     }
01435   }
01436 
01437   sym_map = current_font->GetFamily() == wxSYMBOL;
01438   used_fonts = wxPostScriptDrawText((Scheme_Object *)pstream->f, name, text, dt, combine, use16, current_font_size,
01439                                     sym_map, used_fonts);
01440 
01441   if ((angle != 0.0) || (user_scale_x != 1) || (user_scale_y != 1)) {
01442     pstream->Out("grestore\n"); 
01443   }
01444 
01445   CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y));
01446   if (angle != 0.0) {
01447     double xe, ye;
01448     xe = x + (tw * cos(angle)) + (th * sin(angle));
01449     ye = y - (th * cos(angle)) - (tw * sin(angle));
01450     CalcBoundingBoxClip(XSCALEBND(xe), YSCALEBND(ye));
01451   } else {
01452     CalcBoundingBoxClip(XSCALEBND(x + tw), YSCALEBND(y + th));
01453   }
01454 }
01455 
01456 Bool wxPostScriptDC::GlyphAvailable(int c, wxFont *f)
01457 {
01458   const char *name;
01459   int family, style, weight, sym_map;
01460 
01461   if (!f)
01462     f = current_font;
01463 
01464   family = f->GetFontId();
01465   style = f->GetStyle();
01466   weight = f->GetWeight();
01467 
01468   name = wxTheFontNameDirectory->GetPostScriptName(family, weight, style);
01469   if (!name)
01470     name = "Times-Roman";
01471 
01472   sym_map = current_font->GetFamily() == wxSYMBOL;
01473 
01474   return wxPostScriptGlyphExists(name, c, sym_map);
01475 }
01476 
01477 void wxPostScriptDC::SetBackground (wxColour * c)
01478 {
01479   current_background_color->CopyFrom(c);
01480 }
01481 
01482 void wxPostScriptDC::SetBackgroundMode(int mode)
01483 {
01484   current_bk_mode = mode;
01485 }
01486 
01487 void wxPostScriptDC::SetTextBackground(wxColour *col)
01488 {
01489   current_text_background->CopyFrom(col);  
01490 }
01491 
01492 void wxPostScriptDC::SetTextForeground(wxColour *col)
01493 {
01494   current_text_foreground->CopyFrom(col);
01495 }
01496 
01497 void wxPostScriptDC::TryColour(wxColour *src, wxColour *dest)
01498 {
01499   if (!Colour) {
01500     if ((src->Red() == 255)
01501        && (src->Green() == 255)
01502        && (src->Blue() == 255))
01503       dest->Set(255, 255, 255);
01504     else
01505       dest->Set(0, 0, 0);
01506   } else
01507     dest->CopyFrom(src);
01508 }
01509 
01510 static const char *wxPostScriptHeaderEllipse = "\
01511 /ellipsedict 8 dict def\n\
01512 ellipsedict /mtrx matrix put\n\
01513 /ellipse\n\
01514 { ellipsedict begin\n\
01515   /endangle exch def\n\
01516   /startangle exch def\n\
01517   /yrad exch def\n\
01518   /xrad exch def\n\
01519   /y exch def\n\
01520   /x exch def\n\
01521   /savematrix mtrx currentmatrix def\n\
01522   x y translate\n\
01523   xrad yrad scale\n\
01524   0 0 1 endangle startangle arcn\n\
01525   savematrix setmatrix\n\
01526   end\n\
01527   } def\n\
01528 ";
01529 
01530 Bool wxPostScriptDC::StartDoc (char *message)
01531 {
01532   char userID[256];
01533 
01534   if (device == wxDEVICE_EPS) {
01535     wxPSStream *pss;
01536     pss = new WXGC_PTRS wxPSStream(filename);
01537     pstream = pss;
01538 
01539     if (!pstream || !pstream->good()) {
01540       ok = FALSE;
01541       pstream = NULL;
01542       return FALSE;
01543     }
01544     ok = TRUE;
01545   }
01546 
01547   pstream->Out("%!PS-Adobe-2.0"); /* PostScript magic strings */
01548   if (as_eps) {
01549     pstream->Out(" EPSF-2.0"); /* EPS magic strings */
01550   }
01551   pstream->Out("\n");
01552   if (title) {
01553     pstream->Out("%%Title: "); pstream->Out(title); pstream->Out("\n");
01554   }
01555   pstream->Out("%%Creator: "); pstream->Out("PLT Scheme"); pstream->Out("\n");
01556   pstream->Out("%%CreationDate: "); pstream->Out(wxNow()); pstream->Out("\n");
01557 
01558   // User Id information
01559   if (wxGetEmailAddress(userID, sizeof(userID))) {
01560     char userName[245];
01561     pstream->Out("%%For: "); pstream->Out((char *)userID);
01562     if (wxGetUserName(userName, sizeof(userName))) {
01563       pstream->Out(" ("); pstream->Out((char *)userName); pstream->Out(")");
01564     }
01565     pstream->Out("\n");
01566   } else if ( wxGetUserName(userID, sizeof(userID))) {
01567     pstream->Out("%%For: "); pstream->Out((char *)userID); pstream->Out("\n");
01568   }
01569 
01570   boundingboxpos = pstream->tellp();
01571   pstream->Out("%%BoundingBox: -00000 -00000 -00000 -00000\n");
01572   pstream->Out("%%Pages: -00000\n");
01573 
01574   if (landscape)
01575     pstream->Out("%%Orientation: Landscape\n");
01576 
01577   {
01578     int i;
01579     pstream->Out("%%DocumentFonts: ");  
01580     fontlistpos = pstream->tellp();
01581     for (i = 0; i < 5; i++) {
01582       pstream->Out("          ");  
01583     }
01584     pstream->Out("\n");  
01585   }
01586 
01587   pstream->Out("%%EndComments\n\n");
01588 
01589   pstream->Out(wxPostScriptHeaderEllipse);
01590 
01591   SetBrush(wxWHITE_BRUSH);
01592   SetPen(wxBLACK_PEN);
01593 
01594   page_number = 1;
01595   if (message) {
01596     title = copystring (message);
01597   }
01598 
01599   return TRUE;
01600 }
01601 
01602 #ifdef wx_x
01603 extern void wxsExecute(char **);
01604 #endif
01605 
01606 void wxPostScriptDC::EndDoc (void)
01607 {
01608   double llx, lly, urx, ury;
01609   double minx, miny, maxx, maxy;
01610   long last_pos;
01611 
01612   if (!pstream)
01613     return;
01614   if (clipping) {
01615     clipping = FALSE;
01616     pstream->Out("grestore\n");
01617   }
01618 
01619   // Compute the bounding box.  Note that it is in the default user
01620   // coordinate system, thus we have to convert the values.
01621   // If we're landscape, our sense of "x" and "y" is reversed.
01622   if (use_paper_bbox) {
01623     minx = 0;
01624     miny = 0;
01625     maxx = paper_w;
01626     maxy = paper_h;
01627   } else {
01628     minx = min_x;
01629     miny = min_y;
01630     maxx = max_x;
01631     maxy = max_y;
01632   }
01633    
01634   if (landscape) {
01635     llx = miny * paper_y_scale + paper_y + paper_margin_y;
01636     lly = minx * paper_x_scale + paper_x + paper_margin_x;
01637     urx = maxy * paper_y_scale + paper_y + paper_margin_y;
01638     ury = maxx * paper_x_scale + paper_x + paper_margin_x;
01639   } else {
01640     llx = minx * paper_x_scale + paper_x + paper_margin_x;
01641     lly = paper_h * paper_y_scale - (maxy * paper_y_scale) + paper_y + paper_margin_y;
01642     urx = maxx * paper_x_scale + paper_x + paper_margin_x;
01643     ury = paper_h * paper_y_scale - (miny * paper_y_scale) + paper_y + paper_margin_y;
01644   }
01645 
01646   /* Don't allow a negative-sized bounding box! */
01647   if (urx <= llx)
01648     urx = llx + 1;
01649   if (ury <= lly)
01650     ury = lly + 1;
01651 
01652   last_pos = pstream->tellp();
01653 
01654   // The Adobe specifications call for integers; we round as to make
01655   // the bounding larger.
01656   pstream->seekp(boundingboxpos);
01657   pstream->Out("%%BoundingBox: ");
01658   pstream->width(5);
01659   pstream->Out(floor(llx)); pstream->Out(" ");
01660   pstream->width(5);
01661   pstream->Out(floor(lly)); pstream->Out(" ");
01662   pstream->width(5);
01663   pstream->Out(ceil(urx) ); pstream->Out(" ");
01664   pstream->width(5);
01665   pstream->Out(ceil(ury)); pstream->Out("\n");
01666   pstream->Out("%%Pages: ");
01667   pstream->width(5);
01668   pstream->Out((page_number - 1)); pstream->Out("\n");
01669 
01670   {
01671     char *fnts;
01672     long len;
01673     fnts = wxPostScriptFontsToString(used_fonts);
01674     pstream->seekp(fontlistpos);
01675     len = strlen(fnts);
01676     if (len <= 50) {
01677       pstream->Out(fnts);
01678     } else {
01679       long a, bot, delta = len - 50;
01680       char *buf;
01681       buf = new WXGC_ATOMIC char[4096];
01682       for (a = last_pos; a > fontlistpos; ) {
01683         bot = a - 4095;
01684         if (bot < fontlistpos)
01685           bot = fontlistpos;
01686         pstream->read_at(bot, buf, a - bot);
01687         buf[a - bot] = 0;
01688         pstream->seekp(bot + delta);
01689         pstream->Out(buf);
01690         pstream->flush();
01691         a = bot;
01692       }
01693       pstream->seekp(fontlistpos);
01694       pstream->Out(fnts);
01695     }
01696   }
01697 
01698   DELETE_OBJ pstream;
01699   pstream = NULL;
01700 
01701 #ifdef wx_x
01702   if (ok /* && wx_interactive */)
01703     {
01704       switch (mode) {
01705        case PS_PREVIEW:
01706        {
01707           char *argv[3];
01708          argv[0] = preview_cmd;
01709           argv[1] = filename;
01710           argv[2] = NULL;
01711          wxsExecute (argv);
01712        }
01713        break;
01714 
01715        case PS_PRINTER:
01716        {
01717           char *argv[4];
01718          char *opts;
01719          int i;
01720           argv[0] = print_cmd;
01721          i = 1;
01722          opts = print_opts;
01723          if (opts && *opts)
01724            argv[i++] = opts;
01725          argv[i++] = filename;
01726          argv[i] = NULL;
01727          wxsExecute(argv);
01728        }
01729        break;
01730 
01731        case PS_FILE:
01732          break;
01733        }
01734     }
01735 #endif
01736 }
01737 
01738 void wxPostScriptDC::StartPage (void)
01739 {
01740   if (!pstream)
01741     return;
01742   pstream->Out("%%Page: "); pstream->Out(page_number++); pstream->Out("\n");
01743   pstream->Out("%%BeginPageSetup\n");
01744   /* pstream->Out("userdict /pgsave save put\n"); */
01745 
01746   pstream->Out((paper_x + paper_margin_x + (landscape ? (paper_h * paper_y_scale) : 0)));
01747   pstream->Out(" "); pstream->Out(paper_y + paper_margin_y); pstream->Out(" translate\n");
01748   if (landscape) {
01749     pstream->Out(paper_y_scale); pstream->Out(" "); pstream->Out(paper_x_scale); pstream->Out(" scale\n");
01750     pstream->Out("90 rotate\n");
01751   } else {
01752     pstream->Out(paper_x_scale); pstream->Out(" "); pstream->Out(paper_y_scale); pstream->Out(" scale\n");
01753   }
01754   pstream->Out("2 setlinecap\n");
01755   pstream->Out("%%EndPageSetup\n");
01756 
01757   resetFont = RESET_FONT | RESET_COLOR;
01758   current_font_name = NULL;
01759 
01760   if (clipping)
01761     SetClippingRegion(clipping);
01762 }
01763 
01764 void wxPostScriptDC::EndPage (void)
01765 {
01766   if (!pstream)
01767     return;
01768   /* pstream->Out("userdict /pgsave get restore\n"); */
01769   pstream->Out("showpage\n");
01770 }
01771 
01772 
01773 static void printhex(wxPSStream *pstream, int v)
01774 {
01775   int h, l;
01776   char s[3];
01777 
01778   s[2] = 0;
01779   
01780   h = (v >> 4) & 0xF;
01781   l = v & 0xF;
01782   
01783   if (h <= 9)
01784     s[0] = '0' + h;
01785   else
01786     s[0] = 'a' + (h - 10);
01787   if (l <= 9)
01788     s[1] = '0' + l;
01789   else
01790     s[1] = 'a' + (l - 10);
01791 
01792   pstream->Out(s);
01793 }
01794 
01795 
01796 Bool wxPostScriptDC::
01797 Blit (double xdest, double ydest, double fwidth, double fheight,
01798       wxMemoryDC *src, double xsrc, double ysrc, int rop, wxColour *dcolor,
01799       wxMemoryDC *mask)
01800 {
01801   int mono;
01802   long j, i;
01803   wxColour *c;
01804   int pixel;
01805   int pr, pg, pb;
01806 
01807   wxCanvasDC *source = (wxCanvasDC *)src;
01808   long width, height, x, y;
01809   Bool asColour = level2ok;
01810 
01811   if (!pstream)
01812     return FALSE;
01813 
01814   width = (long)floor(fwidth);
01815   height = (long)floor(fheight);
01816 
01817   if (rop >= 0) {
01818     fwidth = XSCALEREL(fwidth);
01819     fheight = YSCALEREL(fheight);
01820   }
01821 
01822   x = (long)floor(xsrc);
01823   y = (long)floor(ysrc);
01824 
01825   c = new WXGC_PTRS wxColour;
01826 
01827   /* Since we want a definition, may need to start a dictionary: */
01828   if (rop >= 0) {
01829     pstream->Out("1 dict begin\n");
01830   }
01831 
01832   /* Allocate space. */
01833   pstream->Out("/DataString ");
01834   pstream->Out((width * (asColour ? 3 : 1) * ((rop < 0) ? height : 1)));
01835   pstream->Out(" string def\n");
01836 
01837   if (rop < 0) {
01838     pstream->Out(" /PaintProc { begin \n");
01839   }
01840 
01841   /* PostScript setup: */
01842   pstream->Out("gsave\n");
01843   if (rop >= 0) {
01844     pstream->Out(XSCALE(xdest)); pstream->Out(" "); pstream->Out(YSCALE(ydest) - fheight); pstream->Out(" translate\n");
01845   }
01846 
01847   /* Mask => clip */
01848   if (mask) {
01849     int red, green, blue;
01850     int skip_start, skip;
01851     
01852     pstream->Out("newpath\n");
01853     for (i = 0; i < width; i++) {
01854       skip = 0;
01855       skip_start = 0;
01856       for (j = 0; j < height + 1; j++) {
01857        mask->GetPixel(i, j, c);
01858        
01859        if (j == height) {
01860          red = green = blue = 255;
01861        } else {
01862          red = c->Red();
01863          green = c->Green();
01864          blue = c->Blue();
01865        }
01866 
01867        if ((red < 255) || (green < 255) || (blue < 255)) {
01868          skip++;
01869        } else {
01870          if (skip) {
01871            double si, sip, ss, ssk;
01872            si = XSCALEREL(i);
01873            sip = XSCALEREL(i+1);
01874            ss = fheight - YSCALEREL(skip_start);
01875            ssk = fheight - YSCALEREL(skip_start + skip);
01876            pstream->Out(si); pstream->Out(" "); pstream->Out(ss); pstream->Out(" moveto\n");
01877            pstream->Out(sip); pstream->Out(" "); pstream->Out(ss); pstream->Out(" lineto\n");
01878            pstream->Out(sip); pstream->Out(" "); pstream->Out(ssk); pstream->Out(" lineto\n");
01879            pstream->Out(si); pstream->Out(" "); pstream->Out(ssk); pstream->Out(" lineto\n");
01880          }
01881 
01882          skip = 0;
01883          skip_start = j + 1;
01884        }
01885       }
01886     }
01887     pstream->Out("clip\n");
01888   }
01889 
01890   /* Image scale */
01891   pstream->Out(fwidth); pstream->Out(" "); pstream->Out(fheight); pstream->Out(" scale\n");
01892 
01893   /* Image matrix */
01894   pstream->Out(width); pstream->Out(" "); pstream->Out(height); pstream->Out(" 8 [ ");
01895   pstream->Out(width); pstream->Out(" 0 0 "); pstream->Out((-height)); pstream->Out(" 0 "); pstream->Out(height);
01896   pstream->Out(" ]\n");
01897   if (rop >= 0) {
01898     pstream->Out("{\n");
01899     pstream->Out("  currentfile DataString readhexstring pop\n");
01900     pstream->Out("} bind");
01901   } else {
01902     pstream->Out(" { DataString } ");
01903   }
01904   if (asColour) {
01905     pstream->Out(" false 3 colorimage\n");
01906   } else {
01907     pstream->Out(" image\n");
01908   }
01909   
01910   if (rop < 0) {
01911     pstream->Out("grestore\n } def \n");
01912     pstream->Out(" { currentfile DataString readhexstring pop pop } exec\n");
01913   }
01914 
01915   /* Output data as hex digits: */
01916   {
01917     wxBitmap *sbm;
01918     sbm = src->GetObject();
01919     mono = (sbm->GetDepth() == 1);
01920    }
01921 
01922   if (mono && dcolor) {
01923     pr = dcolor->Red();
01924     pg = dcolor->Green();
01925     pb = dcolor->Blue();
01926   } else
01927     pr = pg = pb = 0;
01928 
01929   for (j = 0; j < height; j++) {
01930     for (i = 0; i < width; i++) {
01931       int red, green, blue;
01932 
01933       source->GetPixel(i, j, c);
01934       
01935       red = c->Red();
01936       green = c->Green();
01937       blue = c->Blue();
01938 
01939       if (mono && !red && !green && !blue) {
01940        red = pr;
01941        green = pg;
01942        blue = pb;
01943       } else if (mono) {
01944        if ((rop != wxSOLID) && (rop != (-wxSOLID - 1))) {
01945          red = current_background_color->Red();
01946          green = current_background_color->Green();
01947          blue = current_background_color->Blue();
01948        }
01949       }
01950 
01951       if (asColour) {
01952        printhex(pstream, red);
01953        printhex(pstream, green);
01954        printhex(pstream, blue);
01955 
01956        /* Avoid making lines longer than 255 chars: */
01957        if (i && !(i & 0x1F))
01958          pstream->Out("\n");
01959       } else {
01960        double r, gr, b;
01961 
01962        r = ((double)(red) / 255);
01963        gr = ((double)(green) / 255);
01964        b = ((double)(blue) / 255);
01965 
01966        pixel = (int)(255 * sqrt(((r * r) + (gr * gr) + (b * b)) / 3));
01967        
01968        printhex(pstream, pixel);
01969 
01970        /* Avoid making lines longer than 255 chars: */
01971        if (i && !(i & 0x3F))
01972          pstream->Out("\n");
01973       }
01974 
01975     }
01976     pstream->Out("\n");
01977   }
01978 
01979   if (rop >= 0) {
01980     pstream->Out("grestore\n");
01981     /* End dictionary: */
01982     pstream->Out("end\n");
01983   }
01984 
01985   if (rop >= 0) {
01986     CalcBoundingBoxClip(XSCALEBND(xdest), YSCALEBND(ydest));
01987     /* Bitmap isn't scaled: */
01988     CalcBoundingBoxClip(XSCALEBND(xdest) + fwidth, YSCALEBND(ydest) + fheight);
01989   }
01990 
01991   return TRUE;
01992 }
01993 
01994 static wxMemoryDC *temp_mdc, *temp_mask_mdc;
01995 
01996 Bool wxPostScriptDC::Blit (double xdest, double ydest, double fwidth, double fheight,
01997       wxBitmap *bm, double xsrc, double ysrc, int rop, wxColour *c, wxBitmap *mask)
01998 {
01999   Bool v;
02000   wxMemoryDC *mask_dc = NULL, *main_dc = NULL;
02001 
02002 #ifdef wx_msw
02003   main_dc = (wxMemoryDC *)bm->selectedInto;
02004 #endif
02005   if (!main_dc) {
02006     if (!temp_mdc) {
02007       wxREGGLOB(temp_mdc);
02008       temp_mdc = new WXGC_PTRS wxMemoryDC(1);
02009     }
02010     temp_mdc->SelectObject(bm);
02011     /* Might fail, so we double-check: */
02012     if (temp_mdc->GetObject())
02013       main_dc = temp_mdc;
02014   }
02015 
02016   if (mask) {
02017 #ifdef wx_msw
02018    mask_dc = (wxMemoryDC *)mask->selectedInto;
02019 #endif
02020    if (!mask_dc) {
02021      if (!temp_mask_mdc) {
02022        wxREGGLOB(temp_mask_mdc);
02023        temp_mask_mdc = new WXGC_PTRS wxMemoryDC(1);
02024      } 
02025      temp_mask_mdc->SelectObject(mask);
02026      if (temp_mask_mdc->GetObject()) {
02027        mask_dc = temp_mask_mdc;
02028      }
02029    }
02030   }
02031   
02032   if (main_dc) {
02033     v = Blit(xdest, ydest, fwidth, fheight,
02034             main_dc, xsrc, ysrc, rop, c, mask_dc);
02035     if (main_dc == temp_mdc)
02036       temp_mdc->SelectObject(NULL);
02037   } else
02038     v = FALSE;
02039 
02040   if (mask_dc && (mask_dc == temp_mask_mdc)) {
02041     mask_dc->SelectObject(NULL);
02042   }
02043 
02044   return v;
02045 }
02046 
02047 double wxPostScriptDC::GetCharHeight (void)
02048 {
02049   if (current_font)
02050     return (double) current_font->GetPointSize ();
02051   else
02052     return 12.0;
02053 }
02054 
02055 
02056 double wxPostScriptDC::GetCharWidth (void)
02057 {
02058   return 0;
02059 }
02060 
02061 void wxPostScriptDC::GetTextExtent (const char *string, double *x, double *y,
02062                                 double *descent, double *topSpace, wxFont *theFont,
02063                                 Bool combine, Bool use16, int dt, int slen)
02064 {
02065   wxFont *fontToUse = theFont;
02066   int family;
02067   int size;
02068   int style;
02069   int weight;
02070   int sym_map;
02071   const char *name;
02072 
02073   if (!fontToUse)
02074     fontToUse = current_font;
02075 
02076   family = fontToUse->GetFontId();
02077   size =   fontToUse->GetPointSize();
02078   style =  fontToUse->GetStyle();
02079   weight = fontToUse->GetWeight();
02080 
02081   name = wxTheFontNameDirectory->GetPostScriptName(family, weight, style);
02082   if (!name)
02083     name = "Times-Roman";
02084 
02085   sym_map = fontToUse->GetFamily() == wxSYMBOL;
02086 
02087   wxPostScriptGetTextExtent(name, string, dt, slen, combine, use16, size,
02088                          x, y, descent, topSpace, sym_map);
02089 }
02090 
02091 int wxPostScriptDC::CacheFontMetricsKey()
02092 {
02093   return 2;
02094 }
02095 
02096 void wxPostScriptDC::SetMapMode (int WXXTUNUSED(mode))
02097 {
02098 #ifndef wx_xt
02099   mapping_mode = mode;
02100 #endif
02101   return;
02102 }
02103 
02104 void wxPostScriptDC::SetUserScale (double x, double y)
02105 {
02106   user_scale_x = x;
02107   user_scale_y = y;
02108   resetFont |= RESET_FONT;
02109 }
02110 
02111 double wxPostScriptDC::DeviceToLogicalX(int x)
02112 {
02113   return (x - device_origin_x) / user_scale_x;
02114 }
02115 
02116 double wxPostScriptDC::DeviceToLogicalXRel(int x)
02117 {
02118   return x / user_scale_x;
02119 }
02120 
02121 double wxPostScriptDC::UnscrolledDeviceToLogicalX(int x)
02122 {
02123   return DeviceToLogicalX(x);
02124 }
02125 
02126 double wxPostScriptDC::DeviceToLogicalY(int y)
02127 {
02128   double y2 = -(y - paper_h);
02129   return (y2 - device_origin_y) / user_scale_y;
02130 }
02131 
02132 double wxPostScriptDC::DeviceToLogicalYRel(int y)
02133 {
02134   return y / user_scale_y;
02135 }
02136 
02137 double wxPostScriptDC::UnscrolledDeviceToLogicalY(int y)
02138 {
02139   return DeviceToLogicalY(y);
02140 }
02141 
02142 int wxPostScriptDC::LogicalToDeviceX(double x)
02143 {
02144   return (int)floor(XSCALE(x));
02145 }
02146 
02147 int wxPostScriptDC::LogicalToDeviceXRel(double x)
02148 {
02149   return (int)floor(XSCALEREL(x));
02150 }
02151 
02152 int wxPostScriptDC::LogicalToUnscrolledDeviceX(double x)
02153 {
02154   return LogicalToDeviceX(x);
02155 }
02156 
02157 int wxPostScriptDC::LogicalToDeviceY(double y)
02158 {
02159   return (int)floor(YSCALE(y));
02160 }
02161 
02162 int wxPostScriptDC::LogicalToDeviceYRel(double y)
02163 {
02164   return (int)floor(YSCALEREL(y));
02165 }
02166 
02167 int wxPostScriptDC::LogicalToUnscrolledDeviceY(double y)
02168 {
02169   return LogicalToDeviceY(y);
02170 }
02171 
02172 double wxPostScriptDC::FLogicalToDeviceX(double x)
02173 {
02174   return XSCALE(x);
02175 }
02176 
02177 double wxPostScriptDC::FLogicalToDeviceXRel(double x)
02178 {
02179   return XSCALEREL(x);
02180 }
02181 
02182 double wxPostScriptDC::FLogicalToUnscrolledDeviceX(double x)
02183 {
02184   return FLogicalToDeviceX(x);
02185 }
02186 
02187 double wxPostScriptDC::FLogicalToDeviceY(double y)
02188 {
02189   return YSCALE(y);
02190 }
02191 
02192 double wxPostScriptDC::FLogicalToDeviceYRel(double y)
02193 {
02194   return YSCALEREL(y);
02195 }
02196 
02197 double wxPostScriptDC::FLogicalToUnscrolledDeviceY(double y)
02198 {
02199   return FLogicalToDeviceY(y);
02200 }
02201 
02202 double wxPostScriptDC::FsLogicalToDeviceX(double x, double device_origin_x, double user_scale_x)
02203 {
02204   /* Intentional capture of arguments by macro! */
02205   return XSCALE(x);
02206 }
02207 
02208 double wxPostScriptDC::FsLogicalToDeviceXRel(double x, double device_origin_x, double user_scale_x)
02209 {
02210   /* Intentional capture of arguments by macro! */
02211   return XSCALEREL(x);
02212 }
02213 
02214 double wxPostScriptDC::FsLogicalToDeviceY(double y, double device_origin_y, double user_scale_y)
02215 {
02216   /* Intentional capture of arguments by macro! */
02217   return YSCALE(y);
02218 }
02219 
02220 double wxPostScriptDC::FsLogicalToDeviceYRel(double y, double device_origin_y, double user_scale_y)
02221 {
02222   /* Intentional capture of arguments by macro! */
02223   return YSCALEREL(y);
02224 }
02225 
02226 void wxPostScriptDC::GetSize(double *width, double *height)
02227 {
02228   if (width)
02229     *width = paper_w;
02230   if (height)
02231     *height = paper_h;
02232 }
02233 
02234 void wxPostScriptDC::GetSizeMM(double *WXUNUSED(width), double *WXUNUSED(height))
02235 {
02236 }
02237 
02238 extern Bool wxsPrinterDialog(wxWindow *parent);
02239 
02240 Bool XPrinterDialog(wxWindow *parent)
02241 {
02242   return wxsPrinterDialog(parent);
02243 }
02244 
02245 //-----------------------------------------------------------------------------
02246 // wxPrintSetup implementation
02247 //-----------------------------------------------------------------------------
02248 
02249 #define PS_DEFAULT_PAPER  "Letter 8 1/2 x 11 in"
02250 
02251 #define PS_PREVIEW_COMMAND "gv"
02252 #define PS_PRINTER_COMMAND "lpr"
02253 #define PS_PRINTER_OPTIONS ""
02254 #define PS_AFM_PATH         NULL
02255 
02256 wxPrintSetupData::wxPrintSetupData(void)
02257 {
02258     printer_command = PS_PRINTER_COMMAND;
02259     preview_command = PS_PREVIEW_COMMAND;
02260     printer_flags = PS_PRINTER_OPTIONS;
02261     printer_orient = PS_PORTRAIT;
02262     printer_scale_x = 0.8;
02263     printer_scale_y = 0.8;
02264     printer_translate_x = 0.0;
02265     printer_translate_y = 0.0;
02266 #ifdef wx_x
02267     printer_mode = PS_PREVIEW;
02268 #else
02269     printer_mode = PS_FILE;
02270 #endif
02271     afm_path = default_afm_path;
02272     paper_name = DEFAULT_PAPER;
02273     print_colour = TRUE;
02274     print_level_2 = TRUE;
02275     printer_file = NULL;
02276     emargin_v = emargin_h = 20;
02277     ps_margin_v = ps_margin_h = 16;
02278 }
02279 
02280 wxPrintSetupData::~wxPrintSetupData(void)
02281 {
02282 }
02283 
02284 void wxPrintSetupData::SetPrinterCommand(char *cmd)
02285 {
02286     if (cmd == printer_command)
02287        return;
02288     if (cmd) {
02289        printer_command = copystring(cmd);
02290     } else
02291        printer_command = NULL;
02292 }
02293 
02294 void wxPrintSetupData::SetPrintPreviewCommand(char *cmd)
02295 {
02296     if (cmd == preview_command)
02297        return;
02298     if (cmd) {
02299        preview_command = copystring(cmd);
02300     } else
02301        preview_command = NULL;
02302 }
02303 
02304 void wxPrintSetupData::SetPaperName(char *name)
02305 {
02306   if (name == paper_name)
02307     return;
02308   if (name) {
02309     paper_name = copystring(name);
02310   } else
02311     paper_name = NULL;
02312 }
02313 
02314 void wxPrintSetupData::SetPrinterOptions(char *flags)
02315 {
02316     if (printer_flags == flags)
02317       return;
02318     if (flags) {
02319       printer_flags = copystring(flags);
02320     } else
02321       printer_flags = NULL;
02322 }
02323 
02324 void wxPrintSetupData::SetPrinterFile(char *f)
02325 {
02326     if (f == printer_file)
02327        return;
02328     if (f) {
02329        printer_file = copystring(f);
02330     } else
02331        printer_file = NULL;
02332 }
02333 
02334 void wxPrintSetupData::SetPrinterMode(int mode)
02335 {
02336     printer_mode = PS_FILE;
02337 
02338     if (mode == PS_PREVIEW && preview_command
02339     ||  mode == PS_PRINTER && printer_command)
02340        printer_mode = mode;
02341 }
02342 
02343 void wxPrintSetupData::SetPrinterOrientation(int orient)
02344 { 
02345   printer_orient = orient; 
02346 #ifdef wx_mac
02347   if (native) {
02348     native->SetLandscape(printer_orient == PS_LANDSCAPE);
02349   }
02350 #endif
02351 }
02352 
02353 void wxPrintSetupData::SetAFMPath(char *f)
02354 {
02355     if (f && !default_afm_path) {
02356       wxREGGLOB(default_afm_path);
02357       default_afm_path = f;
02358     }
02359   
02360     if (f == afm_path)
02361        return;
02362     if (f) {
02363       afm_path = copystring(f);
02364     } else
02365        afm_path = NULL;
02366 }
02367 
02368 void wxPrintSetupData::copy(wxPrintSetupData* data)
02369 {
02370   double x, y;
02371   long lx, ly;
02372   char *s;
02373   int i;
02374   
02375   s = data->GetPrinterCommand();
02376   SetPrinterCommand(s);
02377   s = data->GetPrintPreviewCommand();
02378   SetPrintPreviewCommand(s);
02379   s = data->GetPrinterOptions();
02380   SetPrinterOptions(s);
02381   i = data->GetPrinterOrientation();
02382   SetPrinterOrientation(i);
02383   i = data->GetPrinterMode();
02384   SetPrinterMode(i);
02385   s = data->GetAFMPath();
02386   SetAFMPath(s);
02387   s = data->GetPaperName();
02388   SetPaperName(s);
02389   i = data->GetColour();
02390   SetColour(i);
02391   
02392   data->GetPrinterTranslation(&x, &y);
02393   SetPrinterTranslation(x, y);
02394   data->GetPrinterScaling(&x, &y);
02395   SetPrinterScaling(x, y);
02396   data->GetMargin(&x, &y);
02397   SetMargin(x, y);
02398   data->GetEditorMargin(&lx, &ly);
02399   SetEditorMargin(lx, ly);
02400 
02401 #ifdef wx_mac
02402   if (data->native) {
02403     wxPrintData *n;
02404     n = data->native->copy();
02405     native = n;
02406   }
02407 #endif
02408 }
02409 
02410 Bool wxPrintSetupData::CanShowNative()
02411 {
02412 #ifdef wx_mac
02413   return TRUE;
02414 #else
02415   return FALSE;
02416 #endif
02417 }
02418 
02419 Bool wxPrintSetupData::ShowNative(wxWindow *parent)
02420 {
02421 #ifdef wx_mac
02422   wxPrintDialog *d;
02423   int ls;
02424   Bool ok;
02425 
02426   if (!native) {
02427     native = new WXGC_PTRS wxPrintData();
02428     native->SetLandscape(printer_orient == PS_LANDSCAPE);
02429     native->SetScale(printer_scale_y);
02430   }
02431 
02432   d = new WXGC_PTRS wxPrintDialog(parent, native);
02433   ok = d->UseIt();
02434   DELETE_OBJ d;
02435 
02436   if (ok) {
02437     ls = native->GetLandscape();
02438     printer_orient = (ls ? PS_LANDSCAPE : PS_PORTRAIT);
02439     printer_scale_y = native->GetScale();
02440     printer_scale_x = printer_scale_y;
02441   }
02442   return ok;
02443 #else
02444   return TRUE;
02445 #endif
02446 }
02447 
02448 //-----------------------------------------------------------------------------
02449 // wxInitializePrintSetupData
02450 //-----------------------------------------------------------------------------
02451 
02452 void wxInitializePrintSetupData(Bool /* init */)
02453 {
02454   wxPrintSetupData *wxThePrintSetupData;
02455   
02456   wxThePrintSetupData = new WXGC_PTRS wxPrintSetupData;
02457   
02458   wxThePrintSetupData->SetPrintPreviewCommand(PS_PREVIEW_COMMAND);
02459   wxThePrintSetupData->SetPrinterOrientation(PS_PORTRAIT);
02460 #ifdef wx_x
02461   wxThePrintSetupData->SetPrinterMode(PS_PREVIEW);
02462 #else
02463   wxThePrintSetupData->SetPrinterMode(PS_FILE);
02464 #endif
02465   wxThePrintSetupData->SetPaperName(PS_DEFAULT_PAPER);
02466   wxThePrintSetupData->SetPrinterCommand(PS_PRINTER_COMMAND);
02467   wxThePrintSetupData->SetPrinterOptions(PS_PRINTER_OPTIONS);
02468   wxThePrintSetupData->SetAFMPath(PS_AFM_PATH);
02469   
02470   wxSetThePrintSetupData(wxThePrintSetupData);
02471 }
02472 
02473 //-----------------------------------------------------------------------------
02474 // wxPrintPaperType implementation
02475 //-----------------------------------------------------------------------------
02476 
02477 wxPrintPaperType::wxPrintPaperType(char *name, int wmm, int hmm, int wp, int hp)
02478 {
02479     widthMM = wmm;
02480     heightMM = hmm;
02481     widthPixels = wp;
02482     heightPixels = hp;
02483     pageName = copystring(name);
02484 }
02485 
02486 wxPrintPaperType::~wxPrintPaperType(void)
02487 {
02488 }
02489 
02490 
02491 //-----------------------------------------------------------------------------
02492 // wxPrintPaperDatabase implementation
02493 //-----------------------------------------------------------------------------
02494 
02495 wxPrintPaperDatabase::wxPrintPaperDatabase(void) : wxList(wxKEY_STRING)
02496 {
02497     DeleteContents(TRUE);
02498 }
02499 
02500 wxPrintPaperDatabase::~wxPrintPaperDatabase(void)
02501 {
02502 }
02503 
02504 void wxPrintPaperDatabase::CreateDatabase(void)
02505 {
02506     // Need correct values for page size in pixels.
02507     // Each unit is one 'point' = 1/72 of an inch.
02508     // NOTE: WE NEED ALSO TO MAKE ADJUSTMENTS WHEN TRANSLATING
02509     // in wxPostScriptDC code, so we can start from top left.
02510     // So access this database and translate by appropriate number
02511     // of points for this paper size. OR IS IT OK ALREADY?
02512     // Can't remember where the PostScript origin is by default.
02513     // Heck, someone will know how to make it hunky-dory...
02514     // JACS 25/5/95
02515   
02516     AddPaperType("A4 210 x 297 mm", 210, 297,         595, 842);
02517     AddPaperType("A3 297 x 420 mm", 297, 420,         842, 1191);
02518     AddPaperType("Letter 8 1/2 x 11 in", 216, 279,    612, 791);
02519     AddPaperType("Legal 8 1/2 x 14 in", 216, 356,     612, 1009);
02520 }
02521 
02522 void wxPrintPaperDatabase::ClearDatabase(void)
02523 {
02524     Clear();
02525 }
02526 
02527 void wxPrintPaperDatabase::AddPaperType(char *name, int wmm, int hmm,
02528                                    int wp, int hp)
02529 {
02530   wxPrintPaperType *ppt;
02531   ppt = new WXGC_PTRS wxPrintPaperType(name, wmm, hmm, wp, hp);
02532   Append(name, ppt);
02533 }
02534 
02535 wxPrintPaperType *wxPrintPaperDatabase::FindPaperType(char *name)
02536 {
02537   wxNode *node;
02538 
02539   if ((node = Find(name)))
02540     return (wxPrintPaperType*)node->Data();
02541   else
02542     return NULL;
02543 }