/* * File: wb_ps.cc * Purpose: Device context implementation (PostScript) * Author: Julian Smart * Created: 1993 * Updated: August 1994 * Copyright: (c) 2004-2005 PLT Scheme, Inc. * Copyright: (c) 1993, AIAI, University of Edinburgh */ /* This file is the same for all three version of wxWindows from PLT. */ #if defined(_MSC_VER) # include "wx.h" #else #ifdef wx_xt # define Uses_XLib # define Uses_wxList # define Uses_wxWindowDC # define Uses_wxMemoryDC # define Uses_wxPostScriptDC # define Uses_wxPrintSetup # define Uses_wxFontNameDirectory # define Uses_wxDialogBox # define Uses_wxButton # define Uses_wxRadioBox # define Uses_wxText # define Uses_wxChoice # define Uses_wxCheckBox # include "wx.h" # include # include #else # ifdef __GNUG__ # pragma implementation "wx_dcps.h" # pragma implementation # pragma interface #endif # include "common.h" # include "wx_frame.h" # include "wx_dcps.h" # include "wx_dcmem.h" # include "wx_utils.h" # include "wx_dialg.h" # include "wx_cmdlg.h" # include "wx_main.h" # include "wx_lbox.h" # include "wx_rbox.h" # include "wx_buttn.h" # include "wx_choic.h" # include "wx_check.h" # include "wx_messg.h" #ifdef wx_mac # include "wx_print.h" #endif #endif #endif #include "wx_rgn.h" #include "../mzscheme/include/scheme.h" extern void wxPostScriptDrawText(Scheme_Object *f, const char *fontname, const char *text, int dt, Bool combine, int use16, double font_size, int symbol_map); extern void wxPostScriptGetTextExtent(const char *fontname, const char *text, int dt, Bool combine, int use16, double font_size, double *x, double *y, double *descent, double *topSpace, int symbol_map); extern char *wxPostScriptFixupFontName(const char *fontname); extern Bool wxPostScriptGlyphExists(const char *fontname, int c, int symbol_map); # define YSCALE(y) ((paper_h) - ((y) * user_scale_y + device_origin_y)) # define XSCALE(x) ((x) * user_scale_x + device_origin_x) # define YOFFSET(y) ((paper_h) - ((y) + device_origin_y)) # define XOFFSET(x) ((x) + device_origin_x) # define YSCALEREL(dy) ((dy) * user_scale_y) # define XSCALEREL(dx) ((dx) * user_scale_x) # define XSCALEBND(dx) (XSCALEREL(dx) + device_origin_x) # define YSCALEBND(dy) (YSCALEREL(dy) + device_origin_y) # define ASCALEREL(a) ((a) * ascale) # define PIE pie #define RESET_FONT 0x1 #define RESET_COLOR 0x2 static double pie = 0.0; #ifndef WXUNUSED # define WXUNUSED(x) x #endif #ifdef wx_xt # define WXXTUNUSED(c) /* empty */ #else # define WXXTUNUSED(x) x #endif #define DEFAULT_PAPER "Letter 8 1/2 x 11 in" class wxCanvas; #ifdef wx_msw # include "wx_privt.h" #endif #include #include #include static char *default_afm_path = NULL; Bool XPrinterDialog(wxWindow *parent); #ifdef wx_mac wxPrintPaperDatabase *wxThePrintPaperDatabase; #endif #ifndef wx_xt # define current_font font #else # define current_bk_mode current_text_bgmode # define current_text_foreground current_text_fg # define current_text_background current_text_bg #endif /**************************************************/ wxPSStream::wxPSStream(char *file) { f = scheme_open_output_file(file, "post-script-dc%"); int_width = 0; } wxPSStream::~wxPSStream(void) { if (f) scheme_close_output_port((Scheme_Object *)f); } int wxPSStream::good(void) { return !!f; } void wxPSStream::Out(char s) { char s2[2]; s2[0] = s; s2[1] = 0; Out(s2); } void wxPSStream::Out(const char *s) { scheme_put_byte_string("post-script-dc%", (Scheme_Object *)f, s, 0, strlen(s), 0); } void wxPSStream::Out(int i) { Out((long)i); } void wxPSStream::Out(double n) { char buf[64]; if ((double)(long)n == n) { Out((long)n); return; } sprintf(buf, "%f", n); Out(buf); } void wxPSStream::Out(long l) { char buf[64]; if (int_width > 0) { char buffer[50]; sprintf(buffer, "%% %d.%dld", int_width, int_width); sprintf(buf, buffer, l); int_width = 0; } else sprintf(buf, "%ld", l); Out(buf); } long wxPSStream::tellp(void) { return scheme_set_file_position((Scheme_Object *)f, -1); } void wxPSStream::seekp(long pos) { scheme_set_file_position((Scheme_Object *)f, pos); } void wxPSStream::width(int w) { int_width = w; } /**************************************************/ wxPostScriptDC::wxPostScriptDC (Bool interactive, wxWindow *parent, Bool usePaperBBox, Bool asEPS) { Create(interactive, parent, usePaperBBox, asEPS); } Bool wxPostScriptDC::Create(Bool interactive, wxWindow *parent, Bool usePaperBBox, Bool asEPS) { wxPrintSetupData *wxThePrintSetupData; char *paperType; wxPrintPaperType *paper; if (!pie) pie = 2 * asin((double)1.0); __type = wxTYPE_DC_POSTSCRIPT; #ifndef wx_xt wx_interactive = interactive; #endif current_font = wxNORMAL_FONT; device = wxDEVICE_EPS; clipping = NULL; #ifndef wx_xt # ifdef wx_mac logical_origin_x = 0; logical_origin_y = 0; logical_scale_x = 1.0; logical_scale_y = 1.0; # endif device_origin_x = 0; device_origin_y = 0; user_scale_x = 1.0; user_scale_y = 1.0; current_pen = NULL; current_brush = NULL; current_background_color = new wxColour(wxWHITE); current_text_foreground = new wxColour(wxBLACK); mapping_mode = MM_TEXT; #else current_pen = wxBLACK_PEN; current_pen->Lock(1); current_brush = wxWHITE_BRUSH; current_brush->Lock(1); current_background_color->CopyFrom(wxWHITE); #endif title = NULL; filename = NULL; pstream = NULL; min_x = 10000.0; min_y = 10000.0; max_x = -10000.0; max_y = -10000.0; clipx = -100000.0; clipy = -100000.0; clipw = 200000.0; cliph = 200000.0; as_eps = asEPS; ok = PrinterDialog(interactive, parent, usePaperBBox); /* We set these even if !ok, for use with text sizing: */ wxThePrintSetupData = wxGetThePrintSetupData(); level2ok = wxThePrintSetupData->GetLevel2(); afm_path = wxThePrintSetupData->GetAFMPath(); if (!ok) return FALSE; currentRed = 0; currentGreen = 0; currentBlue = 0; Colour = TRUE; paperType = wxThePrintSetupData->GetPaperName(); if (!paperType) paperType = DEFAULT_PAPER; paper = wxThePrintPaperDatabase->FindPaperType(paperType); if (!paper) paper = wxThePrintPaperDatabase->FindPaperType(DEFAULT_PAPER); if (paper) { paper_w = (double)paper->widthPixels; paper_h = (double)paper->heightPixels; } else { paper_w = 1000; paper_h = 1000; } if (wxThePrintSetupData) { wxThePrintSetupData->GetPrinterTranslation(&paper_x, &paper_y); wxThePrintSetupData->GetPrinterScaling(&paper_x_scale, &paper_y_scale); if (wxThePrintSetupData->GetPrinterOrientation() == PS_LANDSCAPE) landscape = 1; else landscape = 0; wxThePrintSetupData->GetMargin(&paper_margin_x, &paper_margin_y); } else { paper_x = paper_y = 0; paper_x_scale = paper_y_scale = 1; paper_margin_x = paper_margin_y = 0; landscape = 0; } if (landscape) { double tmp; tmp = paper_w; paper_w = paper_h; paper_h = tmp; } paper_w -= (paper_margin_x * 2); paper_h -= (paper_margin_y * 2); paper_w /= paper_x_scale; if (paper_w <= 0) paper_w = 1; paper_h /= paper_y_scale; if (paper_h <= 0) paper_h = 1; anti_alias = 1; return ok; } wxPostScriptDC::~wxPostScriptDC (void) { if (current_brush) current_brush->Lock(-1); if (current_pen) current_pen->Lock(-1); if (pstream) DELETE_OBJ pstream; } Bool wxPostScriptDC::PrinterDialog(Bool interactive, wxWindow *parent, Bool usePaperBBox) { wxPrintSetupData *wxThePrintSetupData; char *s; if (interactive) { ok = XPrinterDialog(parent); if (!ok) return FALSE; } else ok = TRUE; wxThePrintSetupData = wxGetThePrintSetupData(); mode = wxThePrintSetupData->GetPrinterMode(); s = wxThePrintSetupData->GetPrintPreviewCommand(); preview_cmd = copystring(s); s = wxThePrintSetupData->GetPrinterCommand(); print_cmd = copystring(s); s = wxThePrintSetupData->GetPrinterOptions(); print_opts = copystring(s); use_paper_bbox = usePaperBBox; if ((mode == PS_PREVIEW) || (mode == PS_PRINTER)) { // For PS_PRINTER action this depends on a Unix-style print spooler // since the wx_printer_file can be destroyed during a session char userId[256]; char tmp[256]; wxGetUserId (userId, sizeof (userId) / sizeof (char)); strcpy(tmp, "/tmp/preview_"); strcat(tmp, userId); strcat(tmp, ".ps"); filename = copystring(tmp); } else if (mode == PS_FILE) { char *file; file = interactive ? (char *)NULL : wxThePrintSetupData->GetPrinterFile(); if (!file) { char *dir = NULL; file = wxThePrintSetupData->GetPrinterFile(); if (file) { dir = wxPathOnly(file); file = wxFileNameFromPath(file); } file = wxFileSelector("Save PostScript As", dir, file, "ps", NULL, wxSAVE, parent, -1, -1); } if (!file) { ok = FALSE; return FALSE; } filename = copystring(file); ok = TRUE; } return ok; } void wxPostScriptDC::SetClippingRect(double cx, double cy, double cw, double ch) { wxRegion *r; if (!pstream) return; r = new wxRegion(this); r->SetRectangle(cx, cy, cw, ch); SetClippingRegion(r); } wxRegion *wxPostScriptDC::GetClippingRegion() { return clipping; } void wxPostScriptDC::SetClippingRegion(wxRegion *r) { if (!pstream) return; if (r && (r->GetDC() != this)) return; if (r) { double x, y, w, h; r->BoundingBox(&x, &y, &w, &h); clipx = XSCALEBND(x); clipy = YSCALEBND(y); clipw = XSCALEREL(w); cliph = YSCALEREL(h); } else { clipx = -100000.0; clipy = -100000.0; clipw = 200000.0; cliph = 200000.0; } if (clipping) { --clipping->locked; clipping = NULL; pstream->Out("initclip\n"); } if (r) { r->InstallPS(this, pstream); clipping = r; clipping->locked++; } } void wxPostScriptDC::CalcBoundingBoxClip(double x, double y) { if (x < clipx) x = clipx; else if (x >= (clipx + clipw)) x = clipx + clipw; if (y < clipy) y = clipy; else if (y >= (clipy + cliph)) y = clipy + cliph; if (x < min_x) min_x = x; if (y < min_y) min_y = y; if (x > max_x) max_x = x; if (y > max_y) max_y = y; } void wxPostScriptDC::SetAntiAlias(int mode) { /* Don't change */ } void wxPostScriptDC::Clear(void) { unsigned char red, blue, green; if (!pstream) return; red = current_background_color->Red(); blue = current_background_color->Blue(); green = current_background_color->Green(); { double redPS = (double) (((int) red) / 255.0); double bluePS = (double) (((int) blue) / 255.0); double greenPS = (double) (((int) green) / 255.0); /* Fill with current background */ pstream->Out("gsave newpath\n"); pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n"); pstream->Out(0); pstream->Out(" "); pstream->Out(0); pstream->Out(" moveto\n"); pstream->Out(0); pstream->Out(" "); pstream->Out(paper_h); pstream->Out(" lineto\n"); pstream->Out(paper_w); pstream->Out(" "); pstream->Out(paper_h); pstream->Out(" lineto\n"); pstream->Out(paper_w); pstream->Out(" "); pstream->Out(0); pstream->Out(" lineto\n"); pstream->Out("closepath\n"); pstream->Out("fill grestore\n"); } } Bool wxPostScriptDC::GetPixel(double WXUNUSED(x), double WXUNUSED(y), wxColour * WXUNUSED(col)) { return FALSE; } void wxPostScriptDC::DrawLine (double x1, double y1, double x2, double y2) { if (!pstream) return; if (current_pen) SetPen (current_pen); pstream->Out("newpath\n"); pstream->Out(XSCALE(x1)); pstream->Out(" "); pstream->Out(YSCALE (y1)); pstream->Out(" moveto\n"); pstream->Out(XSCALE(x2)); pstream->Out(" "); pstream->Out(YSCALE (y2)); pstream->Out(" lineto\n"); pstream->Out("stroke\n"); { /* Need to make bounding box wide enough to show the pen. (Part of the reason for this is to avoid zero-sized boounding boxes.) */ double width; if (current_pen) { width = current_pen->GetWidthF(); width /= 2; } else width = 0; if (!width) width = 0.01; if (x1 == x2) { CalcBoundingBoxClip(XSCALEBND(x1 - width), YSCALEBND(y1)); CalcBoundingBoxClip(XSCALEBND(x2 + width), YSCALEBND(y2)); } else if (y1 == y2) { CalcBoundingBoxClip(XSCALEBND(x1), YSCALEBND(y1 - width)); CalcBoundingBoxClip(XSCALEBND(x2), YSCALEBND(y2 + width)); } else { CalcBoundingBoxClip(XSCALEBND(x1 - width), YSCALEBND(y1 - width)); CalcBoundingBoxClip(XSCALEBND(x2 + width), YSCALEBND(y2 + width)); } } } void wxPostScriptDC::DrawArc (double x, double y, double w, double h, double start, double end) { if (!pstream) return; if (start != end) { double a1, a2, radius, xscale; /* Before we scale: */ CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y)); CalcBoundingBoxClip(XSCALEBND(x + w), YSCALEBND(y + h)); x = XSCALE(x); y = YSCALE(y); w = XSCALEREL(w); h = YSCALEREL(h); radius = (h / 2); xscale = (w / h); a1 = start * (180 / pie); a2 = end * (180 / pie); pstream->Out("gsave\n"); pstream->Out((x + w/2)); pstream->Out(" "); pstream->Out((y - h/2)); pstream->Out(" translate\n"); pstream->Out(xscale); pstream->Out(" "); pstream->Out(1); pstream->Out(" scale\n"); if (current_brush && current_brush->GetStyle () != wxTRANSPARENT) { SetBrush(current_brush); pstream->Out("newpath\n"); pstream->Out(0); pstream->Out(" "); pstream->Out(0); pstream->Out(" moveto\n"); pstream->Out("0 0 "); pstream->Out(radius); pstream->Out(" "); pstream->Out(a1); pstream->Out(" "); pstream->Out(a2); pstream->Out(" arc\n"); pstream->Out("closepath\n"); pstream->Out("fill\n"); } if (current_pen && current_pen->GetStyle () != wxTRANSPARENT) { SetPen(current_pen); pstream->Out("newpath\n"); pstream->Out("0 0 "); pstream->Out(radius); pstream->Out(" "); pstream->Out(a1); pstream->Out(" "); pstream->Out(a2); pstream->Out(" arc\n"); pstream->Out("stroke\n"); } pstream->Out("grestore\n"); resetFont |= RESET_COLOR; } } void wxPostScriptDC::DrawPoint (double x, double y) { if (!pstream) return; if (current_pen) SetPen (current_pen); pstream->Out("newpath\n"); pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" moveto\n"); pstream->Out(XSCALE(x+1)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" lineto\n"); pstream->Out("stroke\n"); CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y)); } void wxPostScriptDC::DrawSpline(double x1, double y1, double x2, double y2, double x3, double y3) { double x21, y21, x22, y22; double xm1, ym1, xm2, ym2; if (!pstream) return; if (current_pen) SetPen (current_pen); pstream->Out("newpath\n"); pstream->Out(XSCALE(x1)); pstream->Out(" "); pstream->Out(YSCALE(y1)); pstream->Out(" moveto "); x21 = (x1 + x2) / 2; y21 = (y1 + y2) / 2; pstream->Out(XSCALE(x21)); pstream->Out(" "); pstream->Out(YSCALE(y21)); pstream->Out(" lineto\n"); x22 = (x2 + x3) / 2; y22 = (y2 + y3) / 2; xm1 = (x21 + x2) / 2; ym1 = (y21 + y2) / 2; xm2 = (x2 + x22) / 2; ym2 = (y2 + y22) / 2; pstream->Out(XSCALE(xm1)); pstream->Out(" "); pstream->Out(YSCALE(ym1)); pstream->Out(" "); pstream->Out(XSCALE(xm2)); pstream->Out(" "); pstream->Out(YSCALE(ym2)); pstream->Out(" "); pstream->Out(XSCALE(x22)); pstream->Out(" "); pstream->Out(YSCALE(y22)); pstream->Out(" curveto\n"); pstream->Out(XSCALE(x3)); pstream->Out(" "); pstream->Out(YSCALE(y3)); pstream->Out(" lineto\n"); pstream->Out("stroke\n"); CalcBoundingBoxClip(XSCALEBND(x1), YSCALEBND(y1)); CalcBoundingBoxClip(XSCALEBND(x2), YSCALEBND(y2)); CalcBoundingBoxClip(XSCALEBND(x3), YSCALEBND(y3)); } void wxPostScriptDC::DrawPolygon (int n, wxPoint points[], double xoffset, double yoffset, int fillStyle) { if (!pstream) return; if (n > 0) { if (current_brush && current_brush->GetStyle () != wxTRANSPARENT) { int i; double xx, yy; SetBrush (current_brush); pstream->Out("newpath\n"); xx = points[0].x + xoffset; yy = (points[0].y + yoffset); pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" moveto\n"); CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy)); for (i = 1; i < n; i++) { xx = points[i].x + xoffset; yy = (points[i].y + yoffset); pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" lineto\n"); CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy)); } pstream->Out(((fillStyle == wxODDEVEN_RULE) ? "eofill\n" : "fill\n")); } if (current_pen && current_pen->GetStyle () != wxTRANSPARENT) { int i; double xx, yy; SetPen (current_pen); pstream->Out("newpath\n"); xx = points[0].x + xoffset; yy = (points[0].y + yoffset); pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" moveto\n"); CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy)); for (i = 1; i < n; i++) { xx = points[i].x + xoffset; yy = (points[i].y + yoffset); pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" lineto\n"); CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy)); } // Close the polygon pstream->Out(" closepath\n"); // Output the line pstream->Out("stroke\n"); } } } void wxPostScriptDC::DrawPath(wxPath *p, double xoff, double yoff, int fillStyle) { int did = 0; if (!pstream) return; if (current_brush && current_brush->GetStyle () != wxTRANSPARENT) { SetBrush (current_brush); pstream->Out("newpath\n"); p->InstallPS(this, pstream, xoff, yoff); pstream->Out(((fillStyle == wxODDEVEN_RULE) ? "eofill\n" : "fill\n")); did = 1; } if (current_pen && current_pen->GetStyle () != wxTRANSPARENT) { SetPen (current_pen); pstream->Out("newpath\n"); p->InstallPS(this, pstream, xoff, yoff); pstream->Out("stroke\n"); did = 1; } if (did) { double x1, x2, y1, y2; p->BoundingBox(&x1, &y1, &x2, &y2); x1 += xoff; x2 += xoff; y1 += yoff; y2 += yoff; CalcBoundingBoxClip(XSCALEBND(x1), YSCALEBND(y1)); CalcBoundingBoxClip(XSCALEBND(x2), YSCALEBND(y2)); } } void wxPostScriptDC::DrawLines (int n, wxPoint points[], double xoffset, double yoffset) { if (!pstream) return; if (n > 0 && current_pen && (current_pen->GetStyle () != wxTRANSPARENT)) { int i; double xx, yy; SetPen(current_pen); pstream->Out("newpath\n"); xx = points[0].x + xoffset; yy = (points[0].y + yoffset); pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" moveto\n"); CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy)); for (i = 1; i < n; i++) { xx = points[i].x + xoffset; yy = (points[i].y + yoffset); pstream->Out(XSCALE(xx)); pstream->Out(" "); pstream->Out(YSCALE(yy)); pstream->Out(" lineto\n"); CalcBoundingBoxClip(XSCALEBND(xx), YSCALEBND(yy)); } pstream->Out("stroke\n"); } } void wxPostScriptDC::DrawRectangle (double x, double y, double width, double height) { if (!pstream) return; if (current_brush && current_brush->GetStyle () != wxTRANSPARENT) { SetBrush (current_brush); pstream->Out("newpath\n"); pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" moveto\n"); pstream->Out(XSCALE(x + width)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" lineto\n"); pstream->Out(XSCALE(x + width)); pstream->Out(" "); pstream->Out(YSCALE (y + height)); pstream->Out(" lineto\n"); pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y + height)); pstream->Out(" lineto\n"); pstream->Out("closepath\n"); pstream->Out("fill\n"); CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y)); CalcBoundingBoxClip(XSCALEBND(x + width), YSCALEBND(y + height)); } if (current_pen && current_pen->GetStyle () != wxTRANSPARENT) { SetPen (current_pen); pstream->Out("newpath\n"); pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" moveto\n"); pstream->Out(XSCALE(x + width)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" lineto\n"); pstream->Out(XSCALE(x + width)); pstream->Out(" "); pstream->Out(YSCALE (y + height)); pstream->Out(" lineto\n"); pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y + height)); pstream->Out(" lineto\n"); pstream->Out("closepath\n"); pstream->Out("stroke\n"); CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y)); CalcBoundingBoxClip(XSCALEBND(x + width), YSCALEBND(y + height)); } } void wxPostScriptDC::DrawRoundedRectangle (double x, double y, double width, double height, double radius) { double ascale; if (!pstream) return; if (radius < 0.0) { // Now, a negative radius is interpreted to mean // 'the proportion of the smallest X or Y dimension' double smallest = 0.0; if (width < height) smallest = width; else smallest = height; radius = (double) (-radius * smallest); } ascale = (user_scale_x < user_scale_y) ? user_scale_x : user_scale_y; if (current_brush && current_brush->GetStyle () != wxTRANSPARENT) { SetBrush (current_brush); // Draw rectangle anticlockwise pstream->Out("newpath\n"); pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y)); pstream->Out(" moveto\n"); pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y) - ASCALEREL(radius)); pstream->Out(" "); pstream->Out(ASCALEREL(radius)); pstream->Out(" 90 180 arc\n"); pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y + height) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(ASCALEREL(radius)); pstream->Out(" 180 270 arc\n"); pstream->Out(XSCALE(x + width) - ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y + height) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(ASCALEREL(radius)); pstream->Out(" 270 0 arc\n"); pstream->Out(XSCALE(x + width) - ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y) - ASCALEREL(radius)); pstream->Out(" "); pstream->Out(ASCALEREL(radius)); pstream->Out(" 0 90 arc\n"); pstream->Out("closepath\n"); pstream->Out("fill\n"); CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y)); CalcBoundingBoxClip(XSCALEBND(x + width), YSCALEBND(y + height)); } if (current_pen && current_pen->GetStyle () != wxTRANSPARENT) { SetPen (current_pen); // Draw rectangle anticlockwise pstream->Out("newpath\n"); pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y)); pstream->Out(" moveto\n"); pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y) - ASCALEREL(radius)); pstream->Out(" "); pstream->Out(ASCALEREL(radius)); pstream->Out(" 90 180 arc\n"); pstream->Out(XSCALE(x) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y + height) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(ASCALEREL(radius)); pstream->Out(" 180 270 arc\n"); pstream->Out(XSCALE(x + width) - ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y + height) + ASCALEREL(radius)); pstream->Out(" "); pstream->Out(ASCALEREL(radius)); pstream->Out(" 270 0 arc\n"); pstream->Out(XSCALE(x + width) - ASCALEREL(radius)); pstream->Out(" "); pstream->Out(YSCALE(y) - ASCALEREL(radius)); pstream->Out(" "); pstream->Out(ASCALEREL(radius)); pstream->Out(" 0 90 arc\n"); pstream->Out("closepath\n"); pstream->Out("stroke\n"); CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y)); CalcBoundingBoxClip(XSCALEBND(x + width), YSCALEBND(y + height)); } } void wxPostScriptDC::DrawEllipse (double x, double y, double width, double height) { if (!pstream) return; if (current_brush && current_brush->GetStyle () != wxTRANSPARENT) { SetBrush (current_brush); pstream->Out("newpath\n"); pstream->Out(XSCALE(x + width / 2)); pstream->Out(" "); pstream->Out(YSCALE(y + height / 2)); pstream->Out(" "); pstream->Out(XSCALEREL(width / 2)); pstream->Out(" "); pstream->Out(YSCALEREL(height / 2)); pstream->Out(" 0 360 ellipse\n"); pstream->Out("fill\n"); CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y)); CalcBoundingBoxClip(XSCALEBND(x + width), YSCALEBND(y + height)); } if (current_pen && current_pen->GetStyle () != wxTRANSPARENT) { SetPen (current_pen); pstream->Out("newpath\n"); pstream->Out(XSCALE(x + width / 2)); pstream->Out(" "); pstream->Out(YSCALE(y + height / 2)); pstream->Out(" "); pstream->Out(XSCALEREL(width / 2)); pstream->Out(" "); pstream->Out(YSCALEREL(height / 2)); pstream->Out(" 0 360 ellipse\n"); pstream->Out("stroke\n"); CalcBoundingBoxClip (XSCALEBND(x), YSCALEBND(y)); CalcBoundingBoxClip (XSCALEBND(x + width), YSCALEBND(y + height)); } } void wxPostScriptDC::SetFont (wxFont * the_font) { char *name; int family, style, weight, size; if (!pstream) return; if ((current_font == the_font) && !(resetFont & RESET_FONT)) return; resetFont -= (resetFont & RESET_FONT); current_font = the_font; family = current_font->GetFontId(); style = current_font->GetStyle(); weight = current_font->GetWeight(); name = wxTheFontNameDirectory->GetPostScriptName(family, weight, style); if (!name) name = "Times-Roman"; size = current_font->GetPointSize(); next_font_name = name; next_font_size = size; } static void set_pattern(wxPostScriptDC *dc, wxPSStream *pstream, wxBitmap *bm, int rop, wxColour *col) { int width, height; width = bm->GetWidth(); height = bm->GetHeight(); pstream->Out("8 dict\n"); pstream->Out("dup\n"); pstream->Out("begin\n"); pstream->Out(" /PatternType 1 def\n"); pstream->Out(" /PaintType 1 def\n"); pstream->Out(" /TilingType 1 def\n"); pstream->Out(" /BBox [ 0 0 "); pstream->Out(width); pstream->Out(" "); pstream->Out(height); pstream->Out(" ] def\n"); pstream->Out(" /XStep "); pstream->Out(width); pstream->Out(" def\n"); pstream->Out(" /YStep "); pstream->Out(height); pstream->Out(" def\n"); dc->Blit(0, 0, width, height, bm, 0, 0, -rop - 1, col); pstream->Out("end\n"); pstream->Out(" matrix makepattern setpattern\n"); } static char *dotted = "[2 5] 2"; static char *short_dashed = "[4 4] 2"; static char *long_dashed = "[4 8] 2"; static char *dotted_dashed = "[6 6 2 6] 4"; void wxPostScriptDC::SetPen (wxPen * pen) { wxPen *oldPen = current_pen; char *psdash = NULL; unsigned char red, blue, green; int val; double width; if (!pstream) return; if (current_pen) current_pen->Lock(-1); if (pen) pen->Lock(1); if ((current_pen = pen) == NULL) return; /* NIL */ // Line width width = pen->GetWidthF(); pstream->Out(XSCALEREL(width)); pstream->Out(" setlinewidth\n"); if (level2ok) { wxBitmap *stipple; stipple = pen->GetStipple(); if (stipple && stipple->Ok()) { int ps; wxColour *pc; ps = pen->GetStyle(); pc = pen->GetColour(); set_pattern(this, pstream, stipple, ps, pc); resetFont |= RESET_COLOR; return; } } switch (pen->GetStyle ()) { case wxDOT: psdash = dotted; break; case wxSHORT_DASH: psdash = short_dashed; break; case wxLONG_DASH: psdash = long_dashed; break; case wxDOT_DASH: psdash = dotted_dashed; break; case wxSOLID: case wxTRANSPARENT: default: psdash = "[] 0"; break; } if (oldPen != pen) { pstream->Out(psdash); pstream->Out(" setdash\n"); } switch (pen->GetCap()) { case wxCAP_ROUND: val = 1; break; case wxCAP_PROJECTING: val = 2; break; default: case wxCAP_BUTT: val = 0; break; } pstream->Out(val); pstream->Out(" setlinecap\n"); switch (pen->GetJoin()) { case wxJOIN_ROUND: val = 1; break; case wxJOIN_BEVEL: val = 2; break; default: case wxJOIN_MITER: val = 0; break; } pstream->Out(val); pstream->Out(" setlinejoin\n"); // Line colour { wxColour *pc; pc = pen->GetColour(); red = pc->Red(); blue = pc->Blue(); green = pc->Green(); } if (!Colour) { // Anything not white is black if (!(red == (unsigned char) 255 && blue == (unsigned char) 255 && green == (unsigned char) 255)) { red = (unsigned char) 0; green = (unsigned char) 0; blue = (unsigned char) 0; } } if (!(red == currentRed && green == currentGreen && blue == currentBlue) || (resetFont & RESET_COLOR)) { double redPS = (double) (((int) red) / 255.0); double bluePS = (double) (((int) blue) / 255.0); double greenPS = (double) (((int) green) / 255.0); pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n"); currentRed = red; currentBlue = blue; currentGreen = green; resetFont -= (resetFont & RESET_COLOR); } } static char *ps_brush_hatch[] = { " 0 0 moveto 8 8", " 0 0 moveto 8 8 lineto closepath stroke 8 0 moveto 0 8", " 8 0 moveto 0 8", " 0 4 moveto 8 4 lineto closepath stroke 4 0 moveto 4 8", " 0 4 moveto 8 4", " 4 0 moveto 4 8", " 0 0 moveto 0.1 0.1" }; void wxPostScriptDC::SetBrush(wxBrush * brush) { unsigned char red, blue, green; int hatch_id; char *hatch_size; double redPS, bluePS, greenPS; if (!pstream) return; if (current_brush) current_brush->Lock(-1); if (brush) brush->Lock(1); if ((current_brush = brush) == NULL) return; if (level2ok) { wxBitmap *stipple; stipple = brush->GetStipple(); if (stipple && stipple->Ok()) { int bs; wxColour *bc; bs = brush->GetStyle(); bc = brush->GetColour(); set_pattern(this, pstream, stipple, bs, bc); resetFont |= RESET_COLOR; return; } } // Brush colour { wxColour *bc; bc = brush->GetColour(); red = bc->Red(); blue = bc->Blue(); green = bc->Green(); } if (!Colour) { // Anything not black is white if (!(red == (unsigned char) 0 && blue == (unsigned char) 0 && green == (unsigned char) 0)) { red = (unsigned char) 255; green = (unsigned char) 255; blue = (unsigned char) 255; } } hatch_id = -1; hatch_size = "8"; switch (brush->GetStyle()) { case wxBDIAGONAL_HATCH: hatch_id = 0; break; case wxCROSSDIAG_HATCH: hatch_id = 1; break; case wxFDIAGONAL_HATCH: hatch_id = 2; break; case wxCROSS_HATCH: hatch_id = 3; break; case wxHORIZONTAL_HATCH: hatch_id = 4; break; case wxVERTICAL_HATCH: hatch_id = 5; break; case wxCOLOR: hatch_id = 6; hatch_size = "0.3"; break; } redPS = (double) (((int) red) / 255.0); bluePS = (double) (((int) blue) / 255.0); greenPS = (double) (((int) green) / 255.0); if (hatch_id > -1) { pstream->Out("7 dict\n"); pstream->Out("dup\n"); pstream->Out("begin\n"); pstream->Out(" /PatternType 1 def\n"); pstream->Out(" /PaintType 1 def\n"); pstream->Out(" /TilingType 1 def\n"); pstream->Out(" /BBox [ 0 0 "); pstream->Out(hatch_size); pstream->Out(" "); pstream->Out(hatch_size); pstream->Out(" ] def\n"); pstream->Out(" /XStep "); pstream->Out(hatch_size); pstream->Out(" def\n"); pstream->Out(" /YStep "); pstream->Out(hatch_size); pstream->Out(" def\n"); pstream->Out(" /PaintProc { begin gsave \n"); pstream->Out(" 0.05 setlinewidth\n"); pstream->Out(" [] 0 setdash\n"); pstream->Out(" "); pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n"); pstream->Out(" "); pstream->Out(ps_brush_hatch[hatch_id]); pstream->Out(" lineto closepath stroke \n"); pstream->Out("grestore\n } def \n"); pstream->Out("end\n"); pstream->Out(" matrix makepattern setpattern\n"); resetFont |= RESET_COLOR; return; } if (!(red == currentRed && green == currentGreen && blue == currentBlue) || (resetFont & RESET_COLOR)) { pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n"); currentRed = red; currentBlue = blue; currentGreen = green; resetFont -= (resetFont & RESET_COLOR); } } void wxPostScriptDC::DrawText(DRAW_TEXT_CONST char *text, double x, double y, Bool combine, Bool use16, int dt, double angle) { double tw, th; const char *name; int sym_map; if (!pstream) return; if (current_font) SetFont (current_font); GetTextExtent(text, &tw, &th, NULL, NULL, NULL, combine, use16, dt); if (current_bk_mode == wxSOLID) { unsigned char red, blue, green; red = current_text_background->Red(); blue = current_text_background->Blue(); green = current_text_background->Green(); { double redPS = (double) (((int) red) / 255.0); double bluePS = (double) (((int) blue) / 255.0); double greenPS = (double) (((int) green) / 255.0); pstream->Out("gsave newpath\n"); pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n"); pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" moveto\n"); pstream->Out(XSCALE(x + tw)); pstream->Out(" "); pstream->Out(YSCALE (y)); pstream->Out(" lineto\n"); pstream->Out(XSCALE(x + tw)); pstream->Out(" "); pstream->Out(YSCALE (y + th)); pstream->Out(" lineto\n"); pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE (y + th)); pstream->Out(" lineto\n"); pstream->Out("closepath\n"); pstream->Out("fill grestore\n"); } } if (current_text_foreground->Ok()) { unsigned char red, blue, green; red = current_text_foreground->Red(); blue = current_text_foreground->Blue(); green = current_text_foreground->Green(); if (!Colour) { // Anything not white is black if (!(red == (unsigned char) 255 && blue == (unsigned char) 255 && green == (unsigned char) 255)) { red = (unsigned char) 0; green = (unsigned char) 0; blue = (unsigned char) 0; } } if (!(red == currentRed && green == currentGreen && blue == currentBlue) || (resetFont & RESET_COLOR)) { double redPS = (double) (((int) red) / 255.0); double bluePS = (double) (((int) blue) / 255.0); double greenPS = (double) (((int) green) / 255.0); pstream->Out(redPS); pstream->Out(" "); pstream->Out(greenPS); pstream->Out(" "); pstream->Out(bluePS); pstream->Out(" setrgbcolor\n"); currentRed = red; currentBlue = blue; currentGreen = green; resetFont -= (resetFont & RESET_COLOR); } } if (next_font_name) { if (!current_font_name || (next_font_size != current_font_size) || strcmp(next_font_name, current_font_name)) { pstream->Out("/"); pstream->Out(wxPostScriptFixupFontName(next_font_name)); pstream->Out(" findfont\n"); pstream->Out(next_font_size); pstream->Out(" scalefont setfont\n"); current_font_size = next_font_size; current_font_name = next_font_name; } name = next_font_name; next_font_name = NULL; } else { int family, style, weight; if (current_font) { family = current_font->GetFontId(); style = current_font->GetStyle(); weight = current_font->GetWeight(); } else { family = wxDEFAULT; style = wxNORMAL; weight = wxNORMAL; } name = wxTheFontNameDirectory->GetPostScriptName(family, weight, style); if (!name) name = "Times-Roman"; } if (angle != 0.0) { pstream->Out("gsave\n"); } if (angle != 0.0) { pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE(y)); pstream->Out(" translate\n"); if ((user_scale_x != 1) || (user_scale_y != 1)) { pstream->Out(user_scale_x); pstream->Out(" "); pstream->Out(user_scale_y); pstream->Out(" scale\n"); } pstream->Out(angle * 180 / pie); pstream->Out(" rotate 0 0 moveto\n"); } else { pstream->Out(XSCALE(x)); pstream->Out(" "); pstream->Out(YSCALE(y)); pstream->Out(" moveto\n"); if ((user_scale_x != 1) || (user_scale_y != 1)) { pstream->Out("gsave\n"); pstream->Out(user_scale_x); pstream->Out(" "); pstream->Out(user_scale_y); pstream->Out(" scale\n"); } } sym_map = current_font->GetFamily() == wxSYMBOL; wxPostScriptDrawText((Scheme_Object *)pstream->f, name, text, dt, combine, use16, current_font_size, sym_map); if ((angle != 0.0) || (user_scale_x != 1) || (user_scale_y != 1)) { pstream->Out("grestore\n"); } CalcBoundingBoxClip(XSCALEBND(x), YSCALEBND(y)); if (angle != 0.0) { double xe, ye; xe = x + (tw * cos(angle)) + (th * sin(angle)); ye = y - (th * cos(angle)) - (tw * sin(angle)); CalcBoundingBoxClip(XSCALEBND(xe), YSCALEBND(ye)); } else { CalcBoundingBoxClip(XSCALEBND(x + tw), YSCALEBND(y + th)); } } Bool wxPostScriptDC::GlyphAvailable(int c, wxFont *f) { const char *name; int family, style, weight, sym_map; if (!f) f = current_font; family = f->GetFontId(); style = f->GetStyle(); weight = f->GetWeight(); name = wxTheFontNameDirectory->GetPostScriptName(family, weight, style); if (!name) name = "Times-Roman"; sym_map = current_font->GetFamily() == wxSYMBOL; return wxPostScriptGlyphExists(name, c, sym_map); } void wxPostScriptDC::SetBackground (wxColour * c) { current_background_color->CopyFrom(c); } void wxPostScriptDC::SetBackgroundMode(int mode) { current_bk_mode = mode; } void wxPostScriptDC::SetTextBackground(wxColour *col) { current_text_background->CopyFrom(col); } void wxPostScriptDC::SetTextForeground(wxColour *col) { current_text_foreground->CopyFrom(col); } void wxPostScriptDC::TryColour(wxColour *src, wxColour *dest) { if (!Colour) { if ((src->Red() == 255) && (src->Green() == 255) && (src->Blue() == 255)) dest->Set(255, 255, 255); else dest->Set(0, 0, 0); } else dest->CopyFrom(src); } static const char *wxPostScriptHeaderEllipse = "\ /ellipsedict 8 dict def\n\ ellipsedict /mtrx matrix put\n\ /ellipse\n\ { ellipsedict begin\n\ /endangle exch def\n\ /startangle exch def\n\ /yrad exch def\n\ /xrad exch def\n\ /y exch def\n\ /x exch def\n\ /savematrix mtrx currentmatrix def\n\ x y translate\n\ xrad yrad scale\n\ 0 0 1 endangle startangle arcn\n\ savematrix setmatrix\n\ end\n\ } def\n\ "; Bool wxPostScriptDC::StartDoc (char *message) { char userID[256]; if (device == wxDEVICE_EPS) { wxPSStream *pss; pss = new wxPSStream(filename); pstream = pss; if (!pstream || !pstream->good()) { ok = FALSE; pstream = NULL; return FALSE; } ok = TRUE; } pstream->Out("%!PS-Adobe-2.0"); /* PostScript magic strings */ if (as_eps) { pstream->Out(" EPSF-2.0"); /* EPS magic strings */ } pstream->Out("\n"); if (title) { pstream->Out("%%Title: "); pstream->Out(title); pstream->Out("\n"); } pstream->Out("%%Creator: "); pstream->Out("MrEd"); pstream->Out("\n"); pstream->Out("%%CreationDate: "); pstream->Out(wxNow()); pstream->Out("\n"); // User Id information if (wxGetEmailAddress(userID, sizeof(userID))) { char userName[245]; pstream->Out("%%For: "); pstream->Out((char *)userID); if (wxGetUserName(userName, sizeof(userName))) { pstream->Out(" ("); pstream->Out((char *)userName); pstream->Out(")"); } pstream->Out("\n"); } else if ( wxGetUserName(userID, sizeof(userID))) { pstream->Out("%%For: "); pstream->Out((char *)userID); pstream->Out("\n"); } boundingboxpos = pstream->tellp(); pstream->Out("%%BoundingBox: -00000 -00000 -00000 -00000\n"); pstream->Out("%%Pages: -00000\n"); if (landscape) pstream->Out("%%Orientation: Landscape\n"); pstream->Out("%%EndComments\n\n"); pstream->Out(wxPostScriptHeaderEllipse); SetBrush(wxWHITE_BRUSH); SetPen(wxBLACK_PEN); page_number = 1; if (message) { title = copystring (message); } return TRUE; } #ifdef wx_x extern void wxsExecute(char **); #endif void wxPostScriptDC::EndDoc (void) { double llx, lly, urx, ury; double minx, miny, maxx, maxy; if (!pstream) return; if (clipping) { clipping = FALSE; pstream->Out("grestore\n"); } // Compute the bounding box. Note that it is in the default user // coordinate system, thus we have to convert the values. // If we're landscape, our sense of "x" and "y" is reversed. if (use_paper_bbox) { minx = 0; miny = 0; maxx = paper_w; maxy = paper_h; } else { minx = min_x; miny = min_y; maxx = max_x; maxy = max_y; } if (landscape) { llx = miny * paper_y_scale + paper_y + paper_margin_y; lly = minx * paper_x_scale + paper_x + paper_margin_x; urx = maxy * paper_y_scale + paper_y + paper_margin_y; ury = maxx * paper_x_scale + paper_x + paper_margin_x; } else { llx = minx * paper_x_scale + paper_x + paper_margin_x; lly = paper_h * paper_y_scale - (maxy * paper_y_scale) + paper_y + paper_margin_y; urx = maxx * paper_x_scale + paper_x + paper_margin_x; ury = paper_h * paper_y_scale - (miny * paper_y_scale) + paper_y + paper_margin_y; } /* Don't allow a negative-sized bounding box! */ if (urx <= llx) urx = llx + 1; if (ury <= lly) ury = lly + 1; // The Adobe specifications call for integers; we round as to make // the bounding larger. pstream->seekp(boundingboxpos); pstream->Out("%%BoundingBox: "); pstream->width(5); pstream->Out(floor(llx)); pstream->Out(" "); pstream->width(5); pstream->Out(floor(lly)); pstream->Out(" "); pstream->width(5); pstream->Out(ceil(urx) ); pstream->Out(" "); pstream->width(5); pstream->Out(ceil(ury)); pstream->Out("\n"); pstream->Out("%%Pages: "); pstream->width(5); pstream->Out((page_number - 1)); pstream->Out("\n"); DELETE_OBJ pstream; pstream = NULL; #ifdef wx_x if (ok /* && wx_interactive */) { switch (mode) { case PS_PREVIEW: { char *argv[3]; argv[0] = preview_cmd; argv[1] = filename; argv[2] = NULL; wxsExecute (argv); } break; case PS_PRINTER: { char *argv[4]; char *opts; int i; argv[0] = print_cmd; i = 1; opts = print_opts; if (opts && *opts) argv[i++] = opts; argv[i++] = filename; argv[i] = NULL; wxsExecute(argv); } break; case PS_FILE: break; } } #endif } void wxPostScriptDC::StartPage (void) { if (!pstream) return; pstream->Out("%%Page: "); pstream->Out(page_number++); pstream->Out("\n"); pstream->Out("%%BeginPageSetup\n"); /* pstream->Out("userdict /pgsave save put\n"); */ pstream->Out((paper_x + paper_margin_x + (landscape ? (paper_h * paper_y_scale) : 0))); pstream->Out(" "); pstream->Out(paper_y + paper_margin_y); pstream->Out(" translate\n"); if (landscape) { pstream->Out(paper_y_scale); pstream->Out(" "); pstream->Out(paper_x_scale); pstream->Out(" scale\n"); pstream->Out("90 rotate\n"); } else { pstream->Out(paper_x_scale); pstream->Out(" "); pstream->Out(paper_y_scale); pstream->Out(" scale\n"); } pstream->Out("2 setlinecap\n"); pstream->Out("%%EndPageSetup\n"); resetFont = RESET_FONT | RESET_COLOR; if (clipping) SetClippingRegion(clipping); } void wxPostScriptDC::EndPage (void) { if (!pstream) return; /* pstream->Out("userdict /pgsave get restore\n"); */ pstream->Out("showpage\n"); } static void printhex(wxPSStream *pstream, int v) { int h, l; char s[3]; s[2] = 0; h = (v >> 4) & 0xF; l = v & 0xF; if (h <= 9) s[0] = '0' + h; else s[0] = 'a' + (h - 10); if (l <= 9) s[1] = '0' + l; else s[1] = 'a' + (l - 10); pstream->Out(s); } Bool wxPostScriptDC:: Blit (double xdest, double ydest, double fwidth, double fheight, wxMemoryDC *src, double xsrc, double ysrc, int rop, wxColour *dcolor, wxMemoryDC *mask) { int mono; long j, i; wxColour *c; int pixel; int pr, pg, pb; wxCanvasDC *source = (wxCanvasDC *)src; long width, height, x, y; Bool asColour = level2ok; if (!pstream) return FALSE; width = (long)floor(fwidth); height = (long)floor(fheight); if (rop >= 0) { fwidth = XSCALEREL(fwidth); fheight = YSCALEREL(fheight); } x = (long)floor(xsrc); y = (long)floor(ysrc); c = new wxColour; /* Since we want a definition, may need to start a dictionary: */ if (rop >= 0) { pstream->Out("1 dict begin\n"); } /* Allocate space. */ pstream->Out("/DataString "); pstream->Out((width * (asColour ? 3 : 1) * ((rop < 0) ? height : 1))); pstream->Out(" string def\n"); if (rop < 0) { pstream->Out(" /PaintProc { begin \n"); } /* PostScript setup: */ pstream->Out("gsave\n"); if (rop >= 0) { pstream->Out(XSCALE(xdest)); pstream->Out(" "); pstream->Out(YSCALE(ydest) - fheight); pstream->Out(" translate\n"); } /* Mask => clip */ if (mask) { int red, green, blue; int skip_start, skip; pstream->Out("newpath\n"); for (i = 0; i < width; i++) { skip = 0; skip_start = 0; for (j = 0; j < height + 1; j++) { mask->GetPixel(i, j, c); if (j == height) { red = green = blue = 255; } else { red = c->Red(); green = c->Green(); blue = c->Blue(); } if ((red < 255) || (green < 255) || (blue < 255)) { skip++; } else { if (skip) { double si, sip, ss, ssk; si = XSCALEREL(i); sip = XSCALEREL(i+1); ss = fheight - YSCALEREL(skip_start); ssk = fheight - YSCALEREL(skip_start + skip); pstream->Out(si); pstream->Out(" "); pstream->Out(ss); pstream->Out(" moveto\n"); pstream->Out(sip); pstream->Out(" "); pstream->Out(ss); pstream->Out(" lineto\n"); pstream->Out(sip); pstream->Out(" "); pstream->Out(ssk); pstream->Out(" lineto\n"); pstream->Out(si); pstream->Out(" "); pstream->Out(ssk); pstream->Out(" lineto\n"); } skip = 0; skip_start = j + 1; } } } pstream->Out("clip\n"); } /* Image scale */ pstream->Out(fwidth); pstream->Out(" "); pstream->Out(fheight); pstream->Out(" scale\n"); /* Image matrix */ pstream->Out(width); pstream->Out(" "); pstream->Out(height); pstream->Out(" 8 [ "); pstream->Out(width); pstream->Out(" 0 0 "); pstream->Out((-height)); pstream->Out(" 0 "); pstream->Out(height); pstream->Out(" ]\n"); if (rop >= 0) { pstream->Out("{\n"); pstream->Out(" currentfile DataString readhexstring pop\n"); pstream->Out("} bind"); } else { pstream->Out(" { DataString } "); } if (asColour) { pstream->Out(" false 3 colorimage\n"); } else { pstream->Out(" image\n"); } if (rop < 0) { pstream->Out("grestore\n } def \n"); pstream->Out(" { currentfile DataString readhexstring pop pop } exec\n"); } /* Output data as hex digits: */ { wxBitmap *sbm; sbm = src->GetObject(); mono = (sbm->GetDepth() == 1); } if (mono && dcolor) { pr = dcolor->Red(); pg = dcolor->Green(); pb = dcolor->Blue(); } else pr = pg = pb = 0; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { int red, green, blue; source->GetPixel(i, j, c); red = c->Red(); green = c->Green(); blue = c->Blue(); if (mono && !red && !green && !blue) { red = pr; green = pg; blue = pb; } else if (mono) { if ((rop != wxSOLID) && (rop != (-wxSOLID - 1))) { red = current_background_color->Red(); green = current_background_color->Green(); blue = current_background_color->Blue(); } } if (asColour) { printhex(pstream, red); printhex(pstream, green); printhex(pstream, blue); /* Avoid making lines longer than 255 chars: */ if (i && !(i & 0x1F)) pstream->Out("\n"); } else { double r, gr, b; r = ((double)(red) / 255); gr = ((double)(green) / 255); b = ((double)(blue) / 255); pixel = (int)(255 * sqrt(((r * r) + (gr * gr) + (b * b)) / 3)); printhex(pstream, pixel); /* Avoid making lines longer than 255 chars: */ if (i && !(i & 0x3F)) pstream->Out("\n"); } } pstream->Out("\n"); } if (rop >= 0) { pstream->Out("grestore\n"); /* End dictionary: */ pstream->Out("end\n"); } if (rop >= 0) { CalcBoundingBoxClip(XSCALEBND(xdest), YSCALEBND(ydest)); /* Bitmap isn't scaled: */ CalcBoundingBoxClip(XSCALEBND(xdest) + fwidth, YSCALEBND(ydest) + fheight); } return TRUE; } static wxMemoryDC *temp_mdc, *temp_mask_mdc; Bool wxPostScriptDC::Blit (double xdest, double ydest, double fwidth, double fheight, wxBitmap *bm, double xsrc, double ysrc, int rop, wxColour *c, wxBitmap *mask) { Bool v; wxMemoryDC *mask_dc = NULL, *main_dc = NULL; #ifdef wx_msw main_dc = (wxMemoryDC *)bm->selectedInto; #endif if (!main_dc) { if (!temp_mdc) { wxREGGLOB(temp_mdc); temp_mdc = new wxMemoryDC(1); } temp_mdc->SelectObject(bm); /* Might fail, so we double-check: */ if (temp_mdc->GetObject()) main_dc = temp_mdc; } if (mask) { #ifdef wx_msw mask_dc = (wxMemoryDC *)mask->selectedInto; #endif if (!mask_dc) { if (!temp_mask_mdc) { wxREGGLOB(temp_mask_mdc); temp_mask_mdc = new wxMemoryDC(1); } temp_mask_mdc->SelectObject(mask); if (temp_mask_mdc->GetObject()) { mask_dc = temp_mask_mdc; } } } if (main_dc) { v = Blit(xdest, ydest, fwidth, fheight, main_dc, xsrc, ysrc, rop, c, mask_dc); if (main_dc == temp_mdc) temp_mdc->SelectObject(NULL); } else v = FALSE; if (mask_dc && (mask_dc == temp_mask_mdc)) { mask_dc->SelectObject(NULL); } return v; } double wxPostScriptDC::GetCharHeight (void) { if (current_font) return (double) current_font->GetPointSize (); else return 12.0; } double wxPostScriptDC::GetCharWidth (void) { return 0; } void wxPostScriptDC::GetTextExtent (const char *string, double *x, double *y, double *descent, double *topSpace, wxFont *theFont, Bool combine, Bool use16, int dt) { wxFont *fontToUse = theFont; int family; int size; int style; int weight; int sym_map; const char *name; if (!fontToUse) fontToUse = current_font; family = fontToUse->GetFontId(); size = fontToUse->GetPointSize(); style = fontToUse->GetStyle(); weight = fontToUse->GetWeight(); name = wxTheFontNameDirectory->GetPostScriptName(family, weight, style); if (!name) name = "Times-Roman"; sym_map = fontToUse->GetFamily() == wxSYMBOL; wxPostScriptGetTextExtent(name, string, dt, combine, use16, size, x, y, descent, topSpace, sym_map); } void wxPostScriptDC::SetMapMode (int WXXTUNUSED(mode)) { #ifndef wx_xt mapping_mode = mode; #endif return; } void wxPostScriptDC::SetUserScale (double x, double y) { user_scale_x = x; user_scale_y = y; resetFont |= RESET_FONT; } double wxPostScriptDC::DeviceToLogicalX(int x) { return (x - device_origin_x) / user_scale_x; } double wxPostScriptDC::DeviceToLogicalXRel(int x) { return x / user_scale_x; } double wxPostScriptDC::DeviceToLogicalY(int y) { double y2 = -(y - paper_h); return (y2 - device_origin_y) / user_scale_y; } double wxPostScriptDC::DeviceToLogicalYRel(int y) { return y / user_scale_y; } int wxPostScriptDC::LogicalToDeviceX(double x) { return (int)floor(XSCALE(x)); } int wxPostScriptDC::LogicalToDeviceXRel(double x) { return (int)floor(XSCALEREL(x)); } int wxPostScriptDC::LogicalToDeviceY(double y) { return (int)floor(YSCALE(y)); } int wxPostScriptDC::LogicalToDeviceYRel(double y) { return (int)floor(YSCALEREL(y)); } double wxPostScriptDC::FLogicalToDeviceX(double x) { return XSCALE(x); } double wxPostScriptDC::FLogicalToDeviceXRel(double x) { return XSCALEREL(x); } double wxPostScriptDC::FLogicalToDeviceY(double y) { return YSCALE(y); } double wxPostScriptDC::FLogicalToDeviceYRel(double y) { return YSCALEREL(y); } double wxPostScriptDC::FsLogicalToDeviceX(double x, double device_origin_x, double user_scale_x) { /* Intentional capture of arguments by macro! */ return XSCALE(x); } double wxPostScriptDC::FsLogicalToDeviceXRel(double x, double device_origin_x, double user_scale_x) { /* Intentional capture of arguments by macro! */ return XSCALEREL(x); } double wxPostScriptDC::FsLogicalToDeviceY(double y, double device_origin_y, double user_scale_y) { /* Intentional capture of arguments by macro! */ return YSCALE(y); } double wxPostScriptDC::FsLogicalToDeviceYRel(double y, double device_origin_y, double user_scale_y) { /* Intentional capture of arguments by macro! */ return YSCALEREL(y); } void wxPostScriptDC::GetSize(double *width, double *height) { if (width) *width = paper_w; if (height) *height = paper_h; } void wxPostScriptDC::GetSizeMM(double *WXUNUSED(width), double *WXUNUSED(height)) { } extern Bool wxsPrinterDialog(wxWindow *parent); Bool XPrinterDialog(wxWindow *parent) { return wxsPrinterDialog(parent); } //----------------------------------------------------------------------------- // wxPrintSetup implementation //----------------------------------------------------------------------------- #define PS_DEFAULT_PAPER "Letter 8 1/2 x 11 in" #define PS_PREVIEW_COMMAND "gv" #define PS_PRINTER_COMMAND "lpr" #define PS_PRINTER_OPTIONS "" #define PS_AFM_PATH NULL wxPrintSetupData::wxPrintSetupData(void) { printer_command = PS_PRINTER_COMMAND; preview_command = PS_PREVIEW_COMMAND; printer_flags = PS_PRINTER_OPTIONS; printer_orient = PS_PORTRAIT; printer_scale_x = 0.8; printer_scale_y = 0.8; printer_translate_x = 0.0; printer_translate_y = 0.0; #ifdef wx_x printer_mode = PS_PREVIEW; #else printer_mode = PS_FILE; #endif afm_path = default_afm_path; paper_name = DEFAULT_PAPER; print_colour = TRUE; print_level_2 = TRUE; printer_file = NULL; emargin_v = emargin_h = 20; ps_margin_v = ps_margin_h = 16; } wxPrintSetupData::~wxPrintSetupData(void) { } void wxPrintSetupData::SetPrinterCommand(char *cmd) { if (cmd == printer_command) return; if (cmd) { printer_command = copystring(cmd); } else printer_command = NULL; } void wxPrintSetupData::SetPrintPreviewCommand(char *cmd) { if (cmd == preview_command) return; if (cmd) { preview_command = copystring(cmd); } else preview_command = NULL; } void wxPrintSetupData::SetPaperName(char *name) { if (name == paper_name) return; if (name) { paper_name = copystring(name); } else paper_name = NULL; } void wxPrintSetupData::SetPrinterOptions(char *flags) { if (printer_flags == flags) return; if (flags) { printer_flags = copystring(flags); } else printer_flags = NULL; } void wxPrintSetupData::SetPrinterFile(char *f) { if (f == printer_file) return; if (f) { printer_file = copystring(f); } else printer_file = NULL; } void wxPrintSetupData::SetPrinterMode(int mode) { printer_mode = PS_FILE; if (mode == PS_PREVIEW && preview_command || mode == PS_PRINTER && printer_command) printer_mode = mode; } void wxPrintSetupData::SetPrinterOrientation(int orient) { printer_orient = orient; #ifdef wx_mac if (native) { native->SetLandscape(printer_orient == PS_LANDSCAPE); } #endif } void wxPrintSetupData::SetAFMPath(char *f) { if (f && !default_afm_path) { wxREGGLOB(default_afm_path); default_afm_path = f; } if (f == afm_path) return; if (f) { afm_path = copystring(f); } else afm_path = NULL; } void wxPrintSetupData::copy(wxPrintSetupData* data) { double x, y; long lx, ly; char *s; int i; s = data->GetPrinterCommand(); SetPrinterCommand(s); s = data->GetPrintPreviewCommand(); SetPrintPreviewCommand(s); s = data->GetPrinterOptions(); SetPrinterOptions(s); i = data->GetPrinterOrientation(); SetPrinterOrientation(i); i = data->GetPrinterMode(); SetPrinterMode(i); s = data->GetAFMPath(); SetAFMPath(s); s = data->GetPaperName(); SetPaperName(s); i = data->GetColour(); SetColour(i); data->GetPrinterTranslation(&x, &y); SetPrinterTranslation(x, y); data->GetPrinterScaling(&x, &y); SetPrinterScaling(x, y); data->GetMargin(&x, &y); SetMargin(x, y); data->GetEditorMargin(&lx, &ly); SetEditorMargin(lx, ly); #ifdef wx_mac if (data->native) { wxPrintData *n; n = data->native->copy(); native = n; } #endif } Bool wxPrintSetupData::CanShowNative() { #ifdef wx_mac return TRUE; #else return FALSE; #endif } Bool wxPrintSetupData::ShowNative(wxWindow *parent) { #ifdef wx_mac wxPrintDialog *d; int ls; Bool ok; if (!native) { native = new wxPrintData(); native->SetLandscape(printer_orient == PS_LANDSCAPE); } d = new wxPrintDialog(parent, native); ok = d->UseIt(); DELETE_OBJ d; if (ok) { ls = native->GetLandscape(); printer_orient = (ls ? PS_LANDSCAPE : PS_PORTRAIT); } return ok; #else return TRUE; #endif } //----------------------------------------------------------------------------- // wxInitializePrintSetupData //----------------------------------------------------------------------------- void wxInitializePrintSetupData(Bool /* init */) { wxPrintSetupData *wxThePrintSetupData; #ifdef wx_mac wxThePrintPaperDatabase = new wxPrintPaperDatabase; wxThePrintPaperDatabase->CreateDatabase(); #endif wxThePrintSetupData = new wxPrintSetupData; wxThePrintSetupData->SetPrintPreviewCommand(PS_PREVIEW_COMMAND); wxThePrintSetupData->SetPrinterOrientation(PS_PORTRAIT); #ifdef wx_x wxThePrintSetupData->SetPrinterMode(PS_PREVIEW); #else wxThePrintSetupData->SetPrinterMode(PS_FILE); #endif wxThePrintSetupData->SetPaperName(PS_DEFAULT_PAPER); wxThePrintSetupData->SetPrinterCommand(PS_PRINTER_COMMAND); wxThePrintSetupData->SetPrinterOptions(PS_PRINTER_OPTIONS); wxThePrintSetupData->SetAFMPath(PS_AFM_PATH); wxSetThePrintSetupData(wxThePrintSetupData); } //----------------------------------------------------------------------------- // wxPrintPaperType implementation //----------------------------------------------------------------------------- wxPrintPaperType::wxPrintPaperType(char *name, int wmm, int hmm, int wp, int hp) { widthMM = wmm; heightMM = hmm; widthPixels = wp; heightPixels = hp; pageName = copystring(name); } wxPrintPaperType::~wxPrintPaperType(void) { } //----------------------------------------------------------------------------- // wxPrintPaperDatabase implementation //----------------------------------------------------------------------------- wxPrintPaperDatabase::wxPrintPaperDatabase(void) : wxList(wxKEY_STRING) { DeleteContents(TRUE); } wxPrintPaperDatabase::~wxPrintPaperDatabase(void) { } void wxPrintPaperDatabase::CreateDatabase(void) { // Need correct values for page size in pixels. // Each unit is one 'point' = 1/72 of an inch. // NOTE: WE NEED ALSO TO MAKE ADJUSTMENTS WHEN TRANSLATING // in wxPostScriptDC code, so we can start from top left. // So access this database and translate by appropriate number // of points for this paper size. OR IS IT OK ALREADY? // Can't remember where the PostScript origin is by default. // Heck, someone will know how to make it hunky-dory... // JACS 25/5/95 AddPaperType("A4 210 x 297 mm", 210, 297, 595, 842); AddPaperType("A3 297 x 420 mm", 297, 420, 842, 1191); AddPaperType("Letter 8 1/2 x 11 in", 216, 279, 612, 791); AddPaperType("Legal 8 1/2 x 14 in", 216, 356, 612, 1009); } void wxPrintPaperDatabase::ClearDatabase(void) { Clear(); } void wxPrintPaperDatabase::AddPaperType(char *name, int wmm, int hmm, int wp, int hp) { wxPrintPaperType *ppt; ppt = new wxPrintPaperType(name, wmm, hmm, wp, hp); Append(name, ppt); } wxPrintPaperType *wxPrintPaperDatabase::FindPaperType(char *name) { wxNode *node; if ((node = Find(name))) return (wxPrintPaperType*)node->Data(); else return NULL; }