summaryrefslogtreecommitdiffstats
path: root/src/bltGrPostscriptOp.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/bltGrPostscriptOp.C')
-rw-r--r--src/bltGrPostscriptOp.C223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/bltGrPostscriptOp.C b/src/bltGrPostscriptOp.C
index a15e67b..ed79088 100644
--- a/src/bltGrPostscriptOp.C
+++ b/src/bltGrPostscriptOp.C
@@ -29,6 +29,229 @@
extern "C" {
#include "bltGraph.h"
+#include "bltOp.h"
};
#include "bltGrPageSetupOp.h"
+#include "bltPs.h"
+
+static int CgetOp(Graph* graphPtr, Tcl_Interp* interp,
+ int objc, Tcl_Obj* const objv[])
+{
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "cget option");
+ return TCL_ERROR;
+ }
+
+ PageSetup *setupPtr = graphPtr->pageSetup_;
+ Tcl_Obj* objPtr = Tk_GetOptionValue(interp,
+ (char*)setupPtr,
+ setupPtr->optionTable,
+ objv[3], graphPtr->tkwin_);
+ if (objPtr == NULL)
+ return TCL_ERROR;
+ else
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+}
+
+static int ConfigureOp(Graph* graphPtr, Tcl_Interp* interp,
+ int objc, Tcl_Obj* const objv[])
+{
+ PageSetup* setupPtr = graphPtr->pageSetup_;
+ if (objc <= 4) {
+ Tcl_Obj* objPtr = Tk_GetOptionInfo(interp, (char*)setupPtr,
+ setupPtr->optionTable,
+ (objc == 4) ? objv[3] : NULL,
+ graphPtr->tkwin_);
+ if (objPtr == NULL)
+ return TCL_ERROR;
+ else
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ else
+ return PageSetupObjConfigure(interp, graphPtr, objc-3, objv+3);
+}
+
+static int OutputOp(Graph* graphPtr, Tcl_Interp* interp,
+ int objc, Tcl_Obj* const objv[])
+{
+ const char *fileName = NULL;
+ Tcl_Channel channel = NULL;
+ if (objc > 3) {
+ fileName = Tcl_GetString(objv[3]);
+ if (fileName[0] != '-') {
+ objv++, objc--; /* First argument is the file name. */
+ channel = Tcl_OpenFileChannel(interp, fileName, "w", 0666);
+ if (!channel)
+ return TCL_ERROR;
+
+ if (Tcl_SetChannelOption(interp, channel, "-translation", "binary")
+ != TCL_OK)
+ return TCL_ERROR;
+ }
+ }
+
+ PostScript *psPtr = Blt_Ps_Create(graphPtr->interp_, graphPtr->pageSetup_);
+
+ if (PageSetupObjConfigure(interp, graphPtr, objc-3, objv+3) != TCL_OK) {
+ if (channel)
+ Tcl_Close(interp, channel);
+ Blt_Ps_Free(psPtr);
+ return TCL_ERROR;
+ }
+
+ if (graphPtr->print(fileName, psPtr) != TCL_OK) {
+ if (channel)
+ Tcl_Close(interp, channel);
+ Blt_Ps_Free(psPtr);
+ return TCL_ERROR;
+ }
+
+ int length;
+ const char *buffer = Blt_Ps_GetValue(psPtr, &length);
+ if (channel) {
+ int nBytes = Tcl_Write(channel, buffer, length);
+ if (nBytes < 0) {
+ Tcl_AppendResult(interp, "error writing file \"", fileName, "\": ",
+ Tcl_PosixError(interp), (char *)NULL);
+ if (channel)
+ Tcl_Close(interp, channel);
+ Blt_Ps_Free(psPtr);
+ return TCL_ERROR;
+ }
+ Tcl_Close(interp, channel);
+ }
+ else
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), buffer, length);
+
+ Blt_Ps_Free(psPtr);
+ return TCL_OK;
+}
+
+static Blt_OpSpec psOps[] =
+ {
+ {"cget", 2, (void*)CgetOp, 4, 4, "option",},
+ {"configure", 2, (void*)ConfigureOp, 3, 0, "?option value?...",},
+ {"output", 1, (void*)OutputOp, 3, 0, "?fileName? ?option value?...",},
+ };
+
+static int nPsOps = sizeof(psOps) / sizeof(Blt_OpSpec);
+
+typedef int (GraphPsProc)(Graph* graphPtr, Tcl_Interp* interp, int objc,
+ Tcl_Obj* const objv[]);
+
+int Blt_PostScriptOp(Graph* graphPtr, Tcl_Interp* interp, int objc,
+ Tcl_Obj* const objv[])
+{
+ GraphPsProc* proc = (GraphPsProc*)Blt_GetOpFromObj(interp, nPsOps, psOps, BLT_OP_ARG2, objc, objv, 0);
+ if (!proc)
+ return TCL_ERROR;
+
+ return (*proc)(graphPtr, interp, objc, objv);
+}
+
+// Support
+
+static void AddComments(Blt_Ps ps, const char **comments)
+{
+ const char **p;
+ for (p = comments; *p; p += 2) {
+ if (*(p+1) == NULL) {
+ break;
+ }
+ Blt_Ps_Format(ps, "%% %s: %s\n", *p, *(p+1));
+ }
+}
+
+int PostScriptPreamble(Graph* graphPtr, const char *fileName, Blt_Ps ps)
+{
+ PageSetup *setupPtr = graphPtr->pageSetup_;
+ time_t ticks;
+ char date[200]; /* Holds the date string from ctime() */
+ char *newline;
+
+ if (fileName == NULL) {
+ fileName = Tk_PathName(graphPtr->tkwin_);
+ }
+ Blt_Ps_Append(ps, "%!PS-Adobe-3.0 EPSF-3.0\n");
+
+ /*
+ * The "BoundingBox" comment is required for EPS files. The box
+ * coordinates are integers, so we need round away from the center of the
+ * box.
+ */
+ Blt_Ps_Format(ps, "%%%%BoundingBox: %d %d %d %d\n",
+ setupPtr->left, setupPtr->paperHeight - setupPtr->top,
+ setupPtr->right, setupPtr->paperHeight - setupPtr->bottom);
+
+ Blt_Ps_Append(ps, "%%Pages: 0\n");
+
+ Blt_Ps_Format(ps, "%%%%Creator: (%s %s %s)\n",
+ PACKAGE_NAME, PACKAGE_VERSION, Tk_Class(graphPtr->tkwin_));
+
+ ticks = time((time_t *) NULL);
+ strcpy(date, ctime(&ticks));
+ newline = date + strlen(date) - 1;
+ if (*newline == '\n') {
+ *newline = '\0';
+ }
+ Blt_Ps_Format(ps, "%%%%CreationDate: (%s)\n", date);
+ Blt_Ps_Format(ps, "%%%%Title: (%s)\n", fileName);
+ Blt_Ps_Append(ps, "%%DocumentData: Clean7Bit\n");
+ if (setupPtr->landscape) {
+ Blt_Ps_Append(ps, "%%Orientation: Landscape\n");
+ } else {
+ Blt_Ps_Append(ps, "%%Orientation: Portrait\n");
+ }
+ Blt_Ps_Append(ps, "%%DocumentNeededResources: font Helvetica Courier\n");
+ AddComments(ps, setupPtr->comments);
+ Blt_Ps_Append(ps, "%%EndComments\n\n");
+ if (Blt_Ps_IncludeFile(graphPtr->interp_, ps, "bltGraph.pro") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (setupPtr->footer) {
+ const char *who;
+
+ who = getenv("LOGNAME");
+ if (who == NULL) {
+ who = "???";
+ }
+ Blt_Ps_VarAppend(ps,
+ "8 /Helvetica SetFont\n",
+ "10 30 moveto\n",
+ "(Date: ", date, ") show\n",
+ "10 20 moveto\n",
+ "(File: ", fileName, ") show\n",
+ "10 10 moveto\n",
+ "(Created by: ", who, "@", Tcl_GetHostName(), ") show\n",
+ "0 0 moveto\n",
+ (char *)NULL);
+ }
+ /*
+ * Set the conversion from PostScript to X11 coordinates. Scale pica to
+ * pixels and flip the y-axis (the origin is the upperleft corner).
+ */
+ Blt_Ps_VarAppend(ps,
+ "% Transform coordinate system to use X11 coordinates\n\n",
+ "% 1. Flip y-axis over by reversing the scale,\n",
+ "% 2. Translate the origin to the other side of the page,\n",
+ "% making the origin the upper left corner\n", (char *)NULL);
+ Blt_Ps_Format(ps, "1 -1 scale\n");
+ /* Papersize is in pixels. Translate the new origin *after* changing the
+ * scale. */
+ Blt_Ps_Format(ps, "0 %d translate\n\n", -setupPtr->paperHeight);
+ Blt_Ps_VarAppend(ps, "% User defined page layout\n\n",
+ "% Set color level\n", (char *)NULL);
+ Blt_Ps_Format(ps, "%% Set origin\n%d %d translate\n\n",
+ setupPtr->left, setupPtr->bottom);
+ if (setupPtr->landscape) {
+ Blt_Ps_Format(ps,
+ "%% Landscape orientation\n0 %g translate\n-90 rotate\n",
+ ((double)graphPtr->width_ * setupPtr->scale));
+ }
+ Blt_Ps_Append(ps, "\n%%EndSetup\n\n");
+ return TCL_OK;
+}
+