📄 ps.cpp
字号:
// $common\ps.cpp 1.5 milbo$ postscript routines// Warning: this is raw research code -- expect it to be quite messy.//// milbo durban dec05#include "all.hpp"#define WARN_TOO_CLOSE 1 // bit fields in ngWarnings byte#define WARN_NOT_CLOCKWISE 2static const int CONF_PsPageHeight = 792; // Postscript page height (Letter)static const int CONF_PsPageWidth = 612; // Postcript coords are -306 to +306 in x directionstatic const char *CONF_sTempFileName = "ps_cpp.tmp";static int ngWarnings;static int gPsMinGray = 0;static int gPsMaxGray = 256;static int gPsImageResolution = 1;static char sgPsPageHeader[PLEN]; // page header, printed before page number//-----------------------------------------------------------------------------void PsDocHeader (FILE *pFile, int nPages){Fprintf(pFile, "%%!PS-Adobe-2.0\n");Fprintf(pFile, "%%%%Pages: %d\n", nPages);Fprintf(pFile, "%%%%BoundingBox: 0 0 612 792\n", nPages);Fprintf(pFile, "\n");}//-----------------------------------------------------------------------------// Make sure sFile is closed before calling this!void PsPatchNbrPages (const char *sFile, int nPages){// The line we want to patch looks like this: %%Pages: 123// We will change it to: %%Pages: nPages// Leave all other lines the sameFILE *pOld = Fopen(sFile, "r");FILE *pNew = Fopen(CONF_sTempFileName, "w");char s[PLEN];while (fgets(s, PLEN-1, pOld)) { if (strncmp(s, "%%Pages: ", 9) == 0) Fprintf(pNew, "%%%%Pages: %d\n", nPages); else if (EOF == fputs(s, pNew)) SysErr("PsPatchNbrPages can't write %s\n", CONF_sTempFileName); }fclose(pOld);fclose(pNew);if (unlink(sFile)) SysErr("PsPatchNbrPages: can't remove %s", sFile);if (rename(CONF_sTempFileName, sFile)) SysErr("PsPatchNbrPages: can't rename %s to %s", CONF_sTempFileName, sFile);}//-----------------------------------------------------------------------------void PsDocFooter (FILE *pFile){Fprintf(pFile, "%%%%EOF\n");}//-----------------------------------------------------------------------------// This also puts the page number at the bottom of the pagevoid PsPageHeader (FILE *pFile, int nPage){Fprintf(pFile, "%%%%Page: %d %d\n", nPage, nPage);Fprintf(pFile, "gsave %d %d translate 0.01 setlinewidth\n", CONF_PsPageWidth/2, CONF_PsPageHeight/2);Fprintf(pFile, "/Times-Roman findfont 12 scalefont setfont\n");Fprintf(pFile, "newpath %d %d moveto (Page %d) show\n", -CONF_PsPageWidth/2 + 10, -CONF_PsPageHeight/2 + 30, nPage);}//-----------------------------------------------------------------------------void PsPageFooter (FILE *pFile){Fprintf(pFile, "grestore showpage\n");}//-----------------------------------------------------------------------------void __cdecl PsPageTitle (FILE *pFile, const char *pArgs, ...) // args like printf{Fprintf(pFile, "%% Page title\n");Fprintf(pFile, "0 0 0 setrgbcolor\n"); // blackFprintf(pFile, "/Times-Roman findfont 14 scalefont setfont\n");char s[PLEN];va_list pArg;va_start(pArg, pArgs);vsprintf(s, pArgs, pArg);va_end(pArg);Fprintf(pFile, "newpath %d %d moveto (%s: %s) show\n", -CONF_PsPageWidth/2 + 10, (CONF_PsPageHeight/2) - 5, sgPsPageHeader, s);}//-----------------------------------------------------------------------------// Helper for PsScreeDiagramstatic double Null (double x){return x;}//-----------------------------------------------------------------------------// Just a crude rendition of the eig values// TODO Fix this to use a different scalevoid PsScreeDiagram (const Vec &EigVals, int nEigs, bool fLog, // in FILE *pFile, double Scale, const char *sMsg) // in{#define CONF_nScreeVBorder (CONF_PsPageHeight/3)#define CONF_nScreeHBorder (CONF_PsPageWidth/4)Fprintf(pFile, "%% Scree diagram\n");Fprintf(pFile, "0 0 0 setrgbcolor\n"); // blackPsPageTitle(pFile, sMsg);Fprintf(pFile, "/Times-Roman findfont 10 scalefont setfont\n");double (* Func)(double x);if (fLog) Func = log;else Func = Null;double FuncEig0 = Func(EigVals(0));for (int i = 0; i < nEigs; i++) Fprintf(pFile, "%.4g %.4g %s\n", ((double)(CONF_PsPageWidth - CONF_nScreeHBorder) * i) / nEigs - (double)CONF_PsPageWidth/2 + CONF_nScreeHBorder, ((double)(CONF_PsPageHeight - CONF_nScreeVBorder) * Func(EigVals(i))) / (FuncEig0 * 2), ((i == 0) ? "moveto" : "lineto"));Fprintf(pFile, "stroke\n");Fprintf(pFile, "%.4g %.4g moveto %.4g %.4g lineto\n", -(double)CONF_PsPageWidth/2 + CONF_nScreeHBorder, ((double)(CONF_PsPageHeight - CONF_nScreeVBorder) * Func(EigVals(nEigs-1))) / (FuncEig0 * 2), (double)CONF_PsPageWidth/2 - 10, ((double)(CONF_PsPageHeight - CONF_nScreeVBorder) * Func(EigVals(nEigs-1))) / (FuncEig0 * 2));Fprintf(pFile, "stroke\n");Fprintf(pFile, "%.4g %.4g moveto %.4g %.4g lineto\n", // y axis -(double)CONF_PsPageWidth/2 + CONF_nScreeHBorder, (double)(CONF_PsPageHeight - CONF_nScreeVBorder) / 2, -(double)CONF_PsPageWidth/2 + CONF_nScreeHBorder, ((double)(CONF_PsPageHeight - CONF_nScreeVBorder) * Func(EigVals(nEigs-1))) / (FuncEig0 * 2));Fprintf(pFile, "stroke\n");for (i = 0; i < nEigs; i ++) // x labels { Fprintf(pFile, "newpath %.4g %.4g moveto (%d) show\n", ((double)(CONF_PsPageWidth - CONF_nScreeHBorder) * i) / nEigs - (double)CONF_PsPageWidth/2 + CONF_nScreeHBorder, ((double)(CONF_PsPageHeight - CONF_nScreeVBorder) * Func(EigVals(nEigs-1))) / (FuncEig0 * 2) - 15, i+1); }double yLast = 1000;for (i = 0; i < nEigs; i ++) // y labels { double y = ((double)(CONF_PsPageHeight - CONF_nScreeVBorder) * Func(EigVals(i))) / (FuncEig0 * 2); Fprintf(pFile, "newpath %.4g %.4g moveto (%.4g) show\n", -(double)CONF_PsPageWidth/2 + CONF_nScreeHBorder - 45, y, EigVals(i)); if (yLast - y < 10) break; yLast = y; }}//-----------------------------------------------------------------------------// Display label near first point 0void PsShapeLabel (const SHAPE &Shape, FILE *pFile, double Scale, const char *sMsg, int i, int j){Fprintf(pFile, "%% Shape label\n");Fprintf(pFile, "0 0 0 setrgbcolor\n"); // blackFprintf(pFile, "/Times-Roman findfont 10 scalefont setfont\n");char s[PLEN];sprintf(s, sMsg, i, j);Fprintf(pFile, "newpath %.4g %.4g moveto (%s) show\n", Scale * (Shape(0, VX)) - 50, Scale * (Shape(0, VY) + 10), s);}//-----------------------------------------------------------------------------static void PsColor (FILE *pFile, unsigned Color){unsigned Blue = Color & 0xff;unsigned Green = (Color >> 8) & 0xff;unsigned Red = (Color >> 16) & 0xff;Fprintf(pFile, "%.2g %.2g %.2g setrgbcolor\n", (double)Red/255, (double)Green/255, (double)Blue/255);}//-----------------------------------------------------------------------------// If Warnings is not null, then warnings are displayed at labels if bits are set in Warningsstatic void PsPointLabels (const SHAPE &Shape, const byte Warnings[], // in FILE *pFile, double Scale, unsigned Color) // in{Fprintf(pFile, "%% Point labels\n");PsColor(pFile, Color);Fprintf(pFile, "/Times-Roman findfont 4 scalefont setfont\n");byte LastWarn = 0;unsigned Blue, Green, Red;for (int iPoint = 0; iPoint < Shape.nrows(); iPoint++) { if (!fPointUsed(Shape, iPoint)) continue; byte Warn = Warnings? Warnings[iPoint]: LastWarn; if (Warn != LastWarn) { LastWarn = Warn; if (Warn) { Red = 0xff; Green = 0; Blue = 0; } else { Red = (Color >> 16) & 0xff; Green = (Color >> 8) & 0xff; Blue = Color & 0xff; } Fprintf(pFile, "%.2g %.2g %.2g setrgbcolor\n", (double)Red/255, (double)Green/255, (double)Blue/255); } Fprintf(pFile, "newpath %.4g %.4g moveto (%d%s%s) show\n", Scale * Shape(iPoint, VX) + 2, ((Warn & WARN_TOO_CLOSE)? Scale * (Shape(iPoint, VY) - 1): Scale * Shape(iPoint, VY) + 2), iPoint, ((Warn & WARN_TOO_CLOSE)? "c":""), ((Warn & WARN_NOT_CLOCKWISE)? "n":"")); }}//-----------------------------------------------------------------------------// If Width is 0, use current width, else set width to Width// If Width less than 0, use dashed lines of specified Width//// sMsg is inserted as a comment in the postscript file.//// TODO need to be consistent about param ordervoid PsShape (const SHAPE &Shape, FILE *pFile, double Scale, unsigned Color, double Width, const char *sMsg, int i, int j){DASSERT(Shape.ncols() == 2);Fprintf(pFile, "%% Shape "); // two %% will actually print one %if (sMsg) Fprintf(pFile, sMsg, i, j);Fprintf(pFile, "\n");if (Width != 0) { if (Width < 0) Fprintf(pFile, "gsave [3] 0 setdash %g setlinewidth\n", -Width); else Fprintf(pFile, "gsave %g setlinewidth\n", Width); }unsigned Blue = Color & 0xff;unsigned Green = (Color >> 8) & 0xff;unsigned Red = (Color >> 16) & 0xff;Fprintf(pFile, "%.2g %.2g %.2g setrgbcolor\n", (double)Red/255, (double)Green/255, (double)Blue/255);int nPoints = Shape.nrows();bool fFirst = true;int iFirst = 0;for (int iPoint = 0; iPoint < nPoints; iPoint++) { if (!fPointUsed(Shape, iPoint)) continue; if (fFirst) { Fprintf(pFile, "%.4g %.4g moveto\n", Scale * Shape(iPoint, VX), Scale * Shape(iPoint, VY)); fFirst = false; iFirst = iPoint; } else Fprintf(pFile, "%.4g %.4g lineto\n", Scale * Shape(iPoint, VX), Scale * Shape(iPoint, VY)); // small dot on the point Fprintf(pFile, "%.4g %.4g %.4g 0 360 arc\n", Scale * Shape(iPoint, VX), Scale * Shape(iPoint, VY), 0.3); }Fprintf(pFile, "stroke\n");// connect last point to first point using a pale lineFprintf(pFile, "%.2g %.2g %.2g setrgbcolor\n", (double)(Red + (255 - Red)/2)/255, (double)(Green + (255 - Green)/2)/255, (double)(Blue + (255 - Blue)/2)/255);Fprintf(pFile, "%.4g %.4g moveto %.4g %.4g lineto\nstroke\n", Scale * Shape(nPoints-1, VX), Scale * Shape(nPoints-1, VY), Scale * Shape(iFirst, VX), Scale * Shape(iFirst, VY));if (Width != 0) Fprintf(pFile, "grestore\n");}//-----------------------------------------------------------------------------// Like PsShape but labels points and adds warnings if any// Warnings can be NULL in which case it won't be used// sMsg is inserted as a comment in the postscript file.void PsAnnotatedShape (const SHAPE &Shape, const byte Warnings[], const char *sFile, FILE *pFile, double Scale, unsigned Color, double Width, const char *sMsg, int i, int j){PsShape(Shape, pFile, Scale, Color, Width, sMsg, i, j);PsPointLabels(Shape, Warnings, pFile, Scale, Color);}//-----------------------------------------------------------------------------void PsCircle (double x, double y, double Size, FILE *pFile, double Scale, unsigned Color, double Width){Fprintf(pFile, "%% Circle\n");if (Width != 0) { if (Width < 0) Fprintf(pFile, "gsave [3] 0 setdash %g setlinewidth\n", -Width); else Fprintf(pFile, "gsave %g setlinewidth\n", Width); }PsColor(pFile, Color);Fprintf(pFile, "%.4g %.4g moveto %.4g %.4g %.4g 0 360 arc stroke\n", Scale * x + Size, Scale * y, Scale * x, Scale * y, Size);if (Width != 0) Fprintf(pFile, "grestore\n");}//-----------------------------------------------------------------------------// TODO could use this in more places//// nSamplePoints is only used if fWhiskers is truevoid __cdecl PsPageShapeImage (int *pnPage, bool fAnnotate, bool fWhiskers, bool fFooter, SHAPE Shape, const tLand Lands[], const SHAPE &AlignedAvShape, const Image &Img, const char sPsFile[], FILE *pPsFile, double PsScale, unsigned Color, double Width, int nSamplePoints, const char *pArgs, ...) // args like printf{char s[PLEN];va_list pArg;va_start(pArg, pArgs);vsprintf(s, pArgs, pArg);va_end(pArg);Check2Cols(Shape, "PsPageShapeImage");PsPageHeader(pPsFile, (*pnPage)++);PsImage(Img, PsScale, pPsFile, s);if (fWhiskers) { byte *Warnings = (byte *)calloc(Shape.nrows(), 1); // Warnings just to help layout in PsAnnotatedShape CheckShape(Warnings, false, Shape, s); PsShapeWithWhiskers(Shape, 1, Warnings, nSamplePoints, sPsFile, pPsFile, PsScale, Color, Width, 0, Lands, AlignedAvShape, s); free(Warnings); }else if (fAnnotate)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -