source: trunk/kitgen/8.x/blt/generic/bltGrPs.c@ 199

Last change on this file since 199 was 175, checked in by demin, 12 years ago

initial commit

File size: 38.7 KB
RevLine 
[175]1
2/*
3 * bltGrPs.c --
4 *
5 * This module implements the "postscript" operation for BLT
6 * graph widget.
7 *
8 * Copyright 1991-1998 Lucent Technologies, Inc.
9 *
10 * Permission to use, copy, modify, and distribute this software and
11 * its documentation for any purpose and without fee is hereby
12 * granted, provided that the above copyright notice appear in all
13 * copies and that both that the copyright notice and warranty
14 * disclaimer appear in supporting documentation, and that the names
15 * of Lucent Technologies any of their entities not be used in
16 * advertising or publicity pertaining to distribution of the software
17 * without specific, written prior permission.
18 *
19 * Lucent Technologies disclaims all warranties with regard to this
20 * software, including all implied warranties of merchantability and
21 * fitness. In no event shall Lucent Technologies be liable for any
22 * special, indirect or consequential damages or any damages
23 * whatsoever resulting from loss of use, data or profits, whether in
24 * an action of contract, negligence or other tortuous action, arising
25 * out of or in connection with the use or performance of this
26 * software.
27 */
28
29/*
30 * -----------------------------------------------------------------
31 *
32 * PostScript routines to print a graph
33 *
34 * -----------------------------------------------------------------
35 */
36#include "bltGraph.h"
37#include <X11/Xutil.h>
38#if defined(__STDC__)
39#include <stdarg.h>
40#else
41#include <varargs.h>
42#endif
43
44#define PS_PREVIEW_EPSI 0
45#define PS_PREVIEW_WMF 1
46#define PS_PREVIEW_TIFF 2
47
48static Tk_OptionParseProc StringToColorMode;
49static Tk_OptionPrintProc ColorModeToString;
50static Tk_CustomOption colorModeOption =
51{
52 StringToColorMode, ColorModeToString, (ClientData)0,
53};
54static Tk_OptionParseProc StringToFormat;
55static Tk_OptionPrintProc FormatToString;
56static Tk_CustomOption formatOption =
57{
58 StringToFormat, FormatToString, (ClientData)0,
59};
60extern Tk_CustomOption bltDistanceOption;
61extern Tk_CustomOption bltPositiveDistanceOption;
62extern Tk_CustomOption bltPadOption;
63
64#define DEF_PS_CENTER "yes"
65#define DEF_PS_COLOR_MAP (char *)NULL
66#define DEF_PS_COLOR_MODE "color"
67#define DEF_PS_DECORATIONS "yes"
68#define DEF_PS_FONT_MAP (char *)NULL
69#define DEF_PS_FOOTER "no"
70#define DEF_PS_HEIGHT "0"
71#define DEF_PS_LANDSCAPE "no"
72#define DEF_PS_MAXPECT "no"
73#define DEF_PS_PADX "1.0i"
74#define DEF_PS_PADY "1.0i"
75#define DEF_PS_PAPERHEIGHT "11.0i"
76#define DEF_PS_PAPERWIDTH "8.5i"
77#define DEF_PS_PREVIEW "no"
78#define DEF_PS_PREVIEW_FORMAT "epsi"
79#define DEF_PS_WIDTH "0"
80
81static Tk_ConfigSpec configSpecs[] =
82{
83 {TK_CONFIG_BOOLEAN, "-center", "center", "Center",
84 DEF_PS_CENTER, Tk_Offset(PostScript, center),
85 TK_CONFIG_DONT_SET_DEFAULT},
86 {TK_CONFIG_STRING, "-colormap", "colorMap", "ColorMap",
87 DEF_PS_COLOR_MAP, Tk_Offset(PostScript, colorVarName),
88 TK_CONFIG_NULL_OK},
89 {TK_CONFIG_CUSTOM, "-colormode", "colorMode", "ColorMode",
90 DEF_PS_COLOR_MODE, Tk_Offset(PostScript, colorMode),
91 TK_CONFIG_DONT_SET_DEFAULT, &colorModeOption},
92 {TK_CONFIG_BOOLEAN, "-decorations", "decorations", "Decorations",
93 DEF_PS_DECORATIONS, Tk_Offset(PostScript, decorations),
94 TK_CONFIG_DONT_SET_DEFAULT},
95 {TK_CONFIG_STRING, "-fontmap", "fontMap", "FontMap",
96 DEF_PS_FONT_MAP, Tk_Offset(PostScript, fontVarName),
97 TK_CONFIG_NULL_OK},
98 {TK_CONFIG_BOOLEAN, "-footer", "footer", "Footer",
99 DEF_PS_FOOTER, Tk_Offset(PostScript, footer),
100 TK_CONFIG_DONT_SET_DEFAULT},
101 {TK_CONFIG_CUSTOM, "-height", "height", "Height",
102 DEF_PS_HEIGHT, Tk_Offset(PostScript, reqHeight),
103 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
104 {TK_CONFIG_BOOLEAN, "-landscape", "landscape", "Landscape",
105 DEF_PS_LANDSCAPE, Tk_Offset(PostScript, landscape),
106 TK_CONFIG_DONT_SET_DEFAULT},
107 {TK_CONFIG_BOOLEAN, "-maxpect", "maxpect", "Maxpect",
108 DEF_PS_MAXPECT, Tk_Offset(PostScript, maxpect),
109 TK_CONFIG_DONT_SET_DEFAULT},
110 {TK_CONFIG_CUSTOM, "-padx", "padX", "PadX",
111 DEF_PS_PADX, Tk_Offset(PostScript, padX), 0, &bltPadOption},
112 {TK_CONFIG_CUSTOM, "-pady", "padY", "PadY",
113 DEF_PS_PADY, Tk_Offset(PostScript, padY), 0, &bltPadOption},
114 {TK_CONFIG_CUSTOM, "-paperheight", "paperHeight", "PaperHeight",
115 DEF_PS_PAPERHEIGHT, Tk_Offset(PostScript, reqPaperHeight),
116 0, &bltPositiveDistanceOption},
117 {TK_CONFIG_CUSTOM, "-paperwidth", "paperWidth", "PaperWidth",
118 DEF_PS_PAPERWIDTH, Tk_Offset(PostScript, reqPaperWidth),
119 0, &bltPositiveDistanceOption},
120 {TK_CONFIG_BOOLEAN, "-preview", "preview", "Preview",
121 DEF_PS_PREVIEW, Tk_Offset(PostScript, addPreview),
122 TK_CONFIG_DONT_SET_DEFAULT},
123 {TK_CONFIG_CUSTOM, "-previewformat", "previewFormat", "PreviewFormat",
124 DEF_PS_PREVIEW_FORMAT, Tk_Offset(PostScript, previewFormat),
125 TK_CONFIG_DONT_SET_DEFAULT, &formatOption},
126 {TK_CONFIG_CUSTOM, "-width", "width", "Width",
127 DEF_PS_WIDTH, Tk_Offset(PostScript, reqWidth),
128 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
129 {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
130};
131
132extern void Blt_MarkersToPostScript _ANSI_ARGS_((Graph *graphPtr,
133 PsToken psToken, int under));
134extern void Blt_ElementsToPostScript _ANSI_ARGS_((Graph *graphPtr,
135 PsToken psToken));
136extern void Blt_ActiveElementsToPostScript _ANSI_ARGS_((Graph *graphPtr,
137 PsToken psToken));
138extern void Blt_LegendToPostScript _ANSI_ARGS_((Legend *legendPtr,
139 PsToken psToken));
140extern void Blt_GridToPostScript _ANSI_ARGS_((Graph *graphPtr,
141 PsToken psToken));
142extern void Blt_AxesToPostScript _ANSI_ARGS_((Graph *graphPtr,
143 PsToken psToken));
144extern void Blt_AxisLimitsToPostScript _ANSI_ARGS_((Graph *graphPtr,
145 PsToken psToken));
146/*
147 *----------------------------------------------------------------------
148 *
149 * StringToColorMode --
150 *
151 * Convert the string representation of a PostScript color mode
152 * into the enumerated type representing the color level:
153 *
154 * PS_MODE_COLOR - Full color
155 * PS_MODE_GREYSCALE - Color converted to greyscale
156 * PS_MODE_MONOCHROME - Only black and white
157 *
158 * Results:
159 * A standard Tcl result. The color level is written into the
160 * page layout information structure.
161 *
162 * Side Effects:
163 * Future invocations of the "postscript" option will use this
164 * variable to determine how color information will be displayed
165 * in the PostScript output it produces.
166 *
167 *----------------------------------------------------------------------
168 */
169/*ARGSUSED*/
170static int
171StringToColorMode(clientData, interp, tkwin, string, widgRec, offset)
172 ClientData clientData; /* Not used. */
173 Tcl_Interp *interp; /* Interpreter to send results back to */
174 Tk_Window tkwin; /* Not used. */
175 char *string; /* New value. */
176 char *widgRec; /* Widget record */
177 int offset; /* Offset of field in record */
178{
179 PsColorMode *modePtr = (PsColorMode *) (widgRec + offset);
180 unsigned int length;
181 char c;
182
183 c = string[0];
184 length = strlen(string);
185 if ((c == 'c') && (strncmp(string, "color", length) == 0)) {
186 *modePtr = PS_MODE_COLOR;
187 } else if ((c == 'g') && (strncmp(string, "grayscale", length) == 0)) {
188 *modePtr = PS_MODE_GREYSCALE;
189 } else if ((c == 'g') && (strncmp(string, "greyscale", length) == 0)) {
190 *modePtr = PS_MODE_GREYSCALE;
191 } else if ((c == 'm') && (strncmp(string, "monochrome", length) == 0)) {
192 *modePtr = PS_MODE_MONOCHROME;
193 } else {
194 Tcl_AppendResult(interp, "bad color mode \"", string, "\": should be \
195\"color\", \"greyscale\", or \"monochrome\"", (char *)NULL);
196 return TCL_ERROR;
197 }
198 return TCL_OK;
199}
200
201/*
202 *----------------------------------------------------------------------
203 *
204 * NameOfColorMode --
205 *
206 * Convert the PostScript mode value into the string representing
207 * a valid color mode.
208 *
209 * Results:
210 * The static string representing the color mode is returned.
211 *
212 *----------------------------------------------------------------------
213 */
214static char *
215NameOfColorMode(colorMode)
216 PsColorMode colorMode;
217{
218 switch (colorMode) {
219 case PS_MODE_COLOR:
220 return "color";
221 case PS_MODE_GREYSCALE:
222 return "greyscale";
223 case PS_MODE_MONOCHROME:
224 return "monochrome";
225 default:
226 return "unknown color mode";
227 }
228}
229
230/*
231 *----------------------------------------------------------------------
232 *
233 * ColorModeToString --
234 *
235 * Convert the current color mode into the string representing a
236 * valid color mode.
237 *
238 * Results:
239 * The string representing the color mode is returned.
240 *
241 *----------------------------------------------------------------------
242 */
243/*ARGSUSED*/
244static char *
245ColorModeToString(clientData, tkwin, widgRec, offset, freeProcPtr)
246 ClientData clientData; /* Not used. */
247 Tk_Window tkwin; /* Not used. */
248 char *widgRec; /* Widget record. */
249 int offset; /* field of colorMode in record */
250 Tcl_FreeProc **freeProcPtr; /* Not used. */
251{
252 PsColorMode mode = *(PsColorMode *) (widgRec + offset);
253
254 return NameOfColorMode(mode);
255}
256
257/*
258 *----------------------------------------------------------------------
259 *
260 * StringToFormat --
261 *
262 * Convert the string of the PostScript preview format into
263 * an enumerated type representing the desired format. The
264 * available formats are:
265 *
266 * PS_PREVIEW_WMF - Windows Metafile.
267 * PS_PREVIEW_TIFF - TIFF bitmap image.
268 * PS_PREVIEW_EPSI - Device independent ASCII preview
269 *
270 * Results:
271 * A standard Tcl result. The format is written into the
272 * page layout information structure.
273 *
274 * Side Effects:
275 * Future invocations of the "postscript" option will use this
276 * variable to determine how to format a preview image (if one
277 * is selected) when the PostScript output is produced.
278 *
279 *----------------------------------------------------------------------
280 */
281/*ARGSUSED*/
282static int
283StringToFormat(clientData, interp, tkwin, string, widgRec, offset)
284 ClientData clientData; /* Not used. */
285 Tcl_Interp *interp; /* Interpreter to send results back to */
286 Tk_Window tkwin; /* Not used. */
287 char *string; /* New value. */
288 char *widgRec; /* Widget record */
289 int offset; /* Offset of field in record */
290{
291 int *formatPtr = (int *) (widgRec + offset);
292 unsigned int length;
293 char c;
294
295 c = string[0];
296 length = strlen(string);
297 if ((c == 'c') && (strncmp(string, "epsi", length) == 0)) {
298 *formatPtr = PS_PREVIEW_EPSI;
299#ifdef WIN32
300#ifdef HAVE_TIFF_H
301 } else if ((c == 't') && (strncmp(string, "tiff", length) == 0)) {
302 *formatPtr = PS_PREVIEW_TIFF;
303#endif /* HAVE_TIFF_H */
304 } else if ((c == 'w') && (strncmp(string, "wmf", length) == 0)) {
305 *formatPtr = PS_PREVIEW_WMF;
306#endif /* WIN32 */
307 } else {
308 Tcl_AppendResult(interp, "bad format \"", string, "\": should be ",
309#ifdef WIN32
310#ifdef HAVE_TIFF_H
311 "\"tiff\" or ",
312#endif /* HAVE_TIFF_H */
313 "\"wmf\" or ",
314#endif /* WIN32 */
315 "\"epsi\"", (char *)NULL);
316 return TCL_ERROR;
317 }
318 return TCL_OK;
319}
320
321/*
322 *----------------------------------------------------------------------
323 *
324 * FormatToString --
325 *
326 * Convert the preview format into the string representing its
327 * type.
328 *
329 * Results:
330 * The string representing the preview format is returned.
331 *
332 *----------------------------------------------------------------------
333 */
334/*ARGSUSED*/
335static char *
336FormatToString(clientData, tkwin, widgRec, offset, freeProcPtr)
337 ClientData clientData; /* Not used. */
338 Tk_Window tkwin; /* Not used. */
339 char *widgRec; /* PostScript structure record */
340 int offset; /* field of colorMode in record */
341 Tcl_FreeProc **freeProcPtr; /* Not used. */
342{
343 int format = *(int *)(widgRec + offset);
344
345 switch (format) {
346 case PS_PREVIEW_EPSI:
347 return "epsi";
348 case PS_PREVIEW_WMF:
349 return "wmf";
350 case PS_PREVIEW_TIFF:
351 return "tiff";
352 }
353 return "?unknown preview format?";
354}
355
356
357void
358Blt_DestroyPostScript(graphPtr)
359 Graph *graphPtr;
360{
361 Tk_FreeOptions(configSpecs, (char *)graphPtr->postscript,
362 graphPtr->display, 0);
363 Blt_Free(graphPtr->postscript);
364}
365
366/*
367 *----------------------------------------------------------------------
368 *
369 * CgetOp --
370 *
371 *----------------------------------------------------------------------
372 */
373/*ARGSUSED*/
374static int
375CgetOp(graphPtr, interp, argc, argv)
376 Graph *graphPtr;
377 Tcl_Interp *interp;
378 int argc;
379 char *argv[];
380{
381 PostScript *psPtr = (PostScript *)graphPtr->postscript;
382
383 if (Tk_ConfigureValue(interp, graphPtr->tkwin, configSpecs, (char *)psPtr,
384 argv[3], 0) != TCL_OK) {
385 return TCL_ERROR;
386 }
387 return TCL_OK;
388}
389
390/*
391 * ----------------------------------------------------------------------
392 *
393 * ConfigureOp --
394 *
395 * This procedure is invoked to print the graph in a file.
396 *
397 * Results:
398 * A standard TCL result.
399 *
400 * Side effects:
401 * A new PostScript file is created.
402 *
403 * ----------------------------------------------------------------------
404 */
405static int
406ConfigureOp(graphPtr, interp, argc, argv)
407 Graph *graphPtr;
408 Tcl_Interp *interp;
409 int argc; /* Number of options in argv vector */
410 char **argv; /* Option vector */
411{
412 int flags = TK_CONFIG_ARGV_ONLY;
413 PostScript *psPtr = (PostScript *)graphPtr->postscript;
414
415 if (argc == 3) {
416 return Tk_ConfigureInfo(interp, graphPtr->tkwin, configSpecs,
417 (char *)psPtr, (char *)NULL, flags);
418 } else if (argc == 4) {
419 return Tk_ConfigureInfo(interp, graphPtr->tkwin, configSpecs,
420 (char *)psPtr, argv[3], flags);
421 }
422 if (Tk_ConfigureWidget(interp, graphPtr->tkwin, configSpecs, argc - 3,
423 argv + 3, (char *)psPtr, flags) != TCL_OK) {
424 return TCL_ERROR;
425 }
426 return TCL_OK;
427}
428
429/*
430 * --------------------------------------------------------------------------
431 *
432 * ComputeBoundingBox --
433 *
434 * Computes the bounding box for the PostScript plot. First get
435 * the size of the plot (by default, it's the size of graph's X
436 * window). If the plot plus the page border is bigger than the
437 * designated paper size, or if the "-maxpect" option is turned
438 * on, scale the plot to the page.
439 *
440 * Note: All coordinates/sizes are in screen coordinates, not
441 * PostScript coordinates. This includes the computed
442 * bounding box and paper size. They will be scaled to
443 * printer points later.
444 *
445 * Results:
446 * Returns the height of the paper in screen coordinates.
447 *
448 * Side Effects:
449 * The graph dimensions (width and height) are changed to the
450 * requested PostScript plot size.
451 *
452 * --------------------------------------------------------------------------
453 */
454static int
455ComputeBoundingBox(graphPtr, psPtr)
456 Graph *graphPtr;
457 PostScript *psPtr;
458{
459 int paperWidth, paperHeight;
460 int x, y, hSize, vSize, hBorder, vBorder;
461 double hScale, vScale, scale;
462
463 x = psPtr->padLeft;
464 y = psPtr->padTop;
465 hBorder = PADDING(psPtr->padX);
466 vBorder = PADDING(psPtr->padY);
467
468 if (psPtr->reqWidth > 0) {
469 graphPtr->width = psPtr->reqWidth;
470 }
471 if (psPtr->reqHeight > 0) {
472 graphPtr->height = psPtr->reqHeight;
473 }
474 if (psPtr->landscape) {
475 hSize = graphPtr->height;
476 vSize = graphPtr->width;
477 } else {
478 hSize = graphPtr->width;
479 vSize = graphPtr->height;
480 }
481 /*
482 * If the paper size wasn't specified, set it to the graph size plus
483 * the paper border.
484 */
485 paperWidth = psPtr->reqPaperWidth;
486 paperHeight = psPtr->reqPaperHeight;
487 if (paperWidth < 1) {
488 paperWidth = hSize + hBorder;
489 }
490 if (paperHeight < 1) {
491 paperHeight = vSize + vBorder;
492 }
493 hScale = vScale = 1.0;
494 /*
495 * Scale the plot size (the graph itself doesn't change size) if
496 * it's bigger than the paper or if -maxpect was set.
497 */
498 if ((psPtr->maxpect) || ((hSize + hBorder) > paperWidth)) {
499 hScale = (double)(paperWidth - hBorder) / (double)hSize;
500 }
501 if ((psPtr->maxpect) || ((vSize + vBorder) > paperHeight)) {
502 vScale = (double)(paperHeight - vBorder) / (double)vSize;
503 }
504 scale = MIN(hScale, vScale);
505 if (scale != 1.0) {
506 hSize = (int)((hSize * scale) + 0.5);
507 vSize = (int)((vSize * scale) + 0.5);
508 }
509 psPtr->pageScale = scale;
510 if (psPtr->center) {
511 if (paperWidth > hSize) {
512 x = (paperWidth - hSize) / 2;
513 }
514 if (paperHeight > vSize) {
515 y = (paperHeight - vSize) / 2;
516 }
517 }
518 psPtr->left = x;
519 psPtr->bottom = y;
520 psPtr->right = x + hSize - 1;
521 psPtr->top = y + vSize - 1;
522
523 graphPtr->flags |= LAYOUT_NEEDED | MAP_WORLD;
524 Blt_LayoutGraph(graphPtr);
525 return paperHeight;
526}
527
528/*
529 * --------------------------------------------------------------------------
530 *
531 * PreviewImage --
532 *
533 * Generates a EPSI thumbnail of the graph. The thumbnail is
534 * restricted to a certain size. This is to keep the size of the
535 * PostScript file small and the processing time low.
536 *
537 * The graph is drawn into a pixmap. We then take a snapshot
538 * of that pixmap, and rescale it to a smaller image. Finally,
539 * the image is dumped to PostScript.
540 *
541 * Results:
542 * None.
543 *
544 * --------------------------------------------------------------------------
545 */
546static void
547PreviewImage(graphPtr, psToken)
548 Graph *graphPtr;
549 PsToken psToken;
550{
551 PostScript *psPtr = (PostScript *)graphPtr->postscript;
552 int noBackingStore = 0;
553 Pixmap drawable;
554 Blt_ColorImage image;
555 int nLines;
556 Tcl_DString dString;
557
558 /* Create a pixmap and draw the graph into it. */
559
560 drawable = Tk_GetPixmap(graphPtr->display, Tk_WindowId(graphPtr->tkwin),
561 graphPtr->width, graphPtr->height, Tk_Depth(graphPtr->tkwin));
562 Blt_DrawGraph(graphPtr, drawable, noBackingStore);
563
564 /* Get a color image from the pixmap */
565 image = Blt_DrawableToColorImage(graphPtr->tkwin, drawable, 0, 0,
566 graphPtr->width, graphPtr->height, 1.0);
567 Tk_FreePixmap(graphPtr->display, drawable);
568 if (image == NULL) {
569 return; /* Can't grab pixmap? */
570 }
571#ifdef THUMBNAIL_PREVIEW
572 {
573 double scale, xScale, yScale;
574 int width, height;
575 Blt_ColorImage destImage;
576
577 /* Scale the source image into a size appropriate for a thumbnail. */
578#define PS_MAX_PREVIEW_WIDTH 300.0
579#define PS_MAX_PREVIEW_HEIGHT 300.0
580 xScale = PS_MAX_PREVIEW_WIDTH / (double)graphPtr->width;
581 yScale = PS_MAX_PREVIEW_HEIGHT / (double)graphPtr->height;
582 scale = MIN(xScale, yScale);
583
584 width = (int)(scale * graphPtr->width + 0.5);
585 height = (int)(scale * graphPtr->height + 0.5);
586 destImage = Blt_ResampleColorImage(image, width, height,
587 bltBoxFilterPtr, bltBoxFilterPtr);
588 Blt_FreeColorImage(image);
589 image = destImage;
590 }
591#endif /* THUMBNAIL_PREVIEW */
592 Blt_ColorImageToGreyscale(image);
593 if (psPtr->landscape) {
594 Blt_ColorImage oldImage;
595
596 oldImage = image;
597 image = Blt_RotateColorImage(image, 90.0);
598 Blt_FreeColorImage(oldImage);
599 }
600 Tcl_DStringInit(&dString);
601 /* Finally, we can generate PostScript for the image */
602 nLines = Blt_ColorImageToPsData(image, 1, &dString, "%");
603
604 Blt_AppendToPostScript(psToken, "%%BeginPreview: ", (char *)NULL);
605 Blt_FormatToPostScript(psToken, "%d %d 8 %d\n", Blt_ColorImageWidth(image),
606 Blt_ColorImageHeight(image), nLines);
607 Blt_AppendToPostScript(psToken, Tcl_DStringValue(&dString), (char *)NULL);
608 Blt_AppendToPostScript(psToken, "%%EndPreview\n\n", (char *)NULL);
609 Tcl_DStringFree(&dString);
610 Blt_FreeColorImage(image);
611}
612
613/*
614 * --------------------------------------------------------------------------
615 *
616 * PostScriptPreamble
617 *
618 * The PostScript preamble calculates the needed translation and scaling
619 * to make X11 coordinates compatible with PostScript.
620 *
621 * ---------------------------------------------------------------------
622 */
623
624#ifdef TIME_WITH_SYS_TIME
625#include <sys/time.h>
626#include <time.h>
627#else
628#ifdef HAVE_SYS_TIME_H
629#include <sys/time.h>
630#else
631#include <time.h>
632#endif /* HAVE_SYS_TIME_H */
633#endif /* TIME_WITH_SYS_TIME */
634
635static int
636PostScriptPreamble(graphPtr, fileName, psToken)
637 Graph *graphPtr;
638 char *fileName;
639 PsToken psToken;
640{
641 PostScript *psPtr = (PostScript *)graphPtr->postscript;
642 time_t ticks;
643 char date[200]; /* Hold the date string from ctime() */
644 CONST char *version;
645 double dpiX, dpiY;
646 double xPixelsToPica, yPixelsToPica; /* Scales to convert pixels to pica */
647 Screen *screenPtr;
648 char *nl;
649 int paperHeightPixels;
650
651 paperHeightPixels = ComputeBoundingBox(graphPtr, psPtr);
652 if (fileName == NULL) {
653 fileName = Tk_PathName(graphPtr->tkwin);
654 }
655 Blt_AppendToPostScript(psToken, "%!PS-Adobe-3.0 EPSF-3.0\n",
656 (char *)NULL);
657
658 /*
659 * Compute the scale factors to convert PostScript to X11 coordinates.
660 * Round the pixels per inch (dpi) to an integral value before computing
661 * the scale.
662 */
663#define MM_INCH 25.4
664#define PICA_INCH 72.0
665 screenPtr = Tk_Screen(graphPtr->tkwin);
666 dpiX = (WidthOfScreen(screenPtr) * MM_INCH) / WidthMMOfScreen(screenPtr);
667 xPixelsToPica = PICA_INCH / dpiX;
668 dpiY = (HeightOfScreen(screenPtr) * MM_INCH) / HeightMMOfScreen(screenPtr);
669 yPixelsToPica = PICA_INCH / dpiY;
670
671 /*
672 * The "BoundingBox" comment is required for EPS files. The box
673 * coordinates are integers, so we need round away from the
674 * center of the box.
675 */
676 Blt_FormatToPostScript(psToken, "%%%%BoundingBox: %d %d %d %d\n",
677 (int)floor(psPtr->left * xPixelsToPica),
678 (int)floor((paperHeightPixels - psPtr->top) * yPixelsToPica),
679 (int)ceil(psPtr->right * xPixelsToPica),
680 (int)ceil((paperHeightPixels - psPtr->bottom) * yPixelsToPica));
681
682 Blt_AppendToPostScript(psToken, "%%Pages: 0\n", (char *)NULL);
683
684 version = Tcl_GetVar(graphPtr->interp, "blt_version", TCL_GLOBAL_ONLY);
685 if (version == NULL) {
686 version = "???";
687 }
688 Blt_FormatToPostScript(psToken, "%%%%Creator: (BLT %s %s)\n", version,
689 Tk_Class(graphPtr->tkwin));
690
691 ticks = time((time_t *) NULL);
692 strcpy(date, ctime(&ticks));
693 nl = date + strlen(date) - 1;
694 if (*nl == '\n') {
695 *nl = '\0';
696 }
697 Blt_FormatToPostScript(psToken, "%%%%CreationDate: (%s)\n", date);
698 Blt_FormatToPostScript(psToken, "%%%%Title: (%s)\n", fileName);
699 Blt_AppendToPostScript(psToken, "%%DocumentData: Clean7Bit\n",
700 (char *)NULL);
701 if (psPtr->landscape) {
702 Blt_AppendToPostScript(psToken, "%%Orientation: Landscape\n",
703 (char *)NULL);
704 } else {
705 Blt_AppendToPostScript(psToken, "%%Orientation: Portrait\n",
706 (char *)NULL);
707 }
708 Blt_AppendToPostScript(psToken,
709 "%%DocumentNeededResources: font Helvetica Courier\n", (char *)NULL);
710 Blt_AppendToPostScript(psToken, "%%EndComments\n\n", (char *)NULL);
711 if ((psPtr->addPreview) && (psPtr->previewFormat == PS_PREVIEW_EPSI)) {
712 PreviewImage(graphPtr, psToken);
713 }
714 if (Blt_FileToPostScript(psToken, "bltGraph.pro") != TCL_OK) {
715 return TCL_ERROR;
716 }
717 if (psPtr->footer) {
718 char *who;
719
720 who = getenv("LOGNAME");
721 if (who == NULL) {
722 who = "???";
723 }
724 Blt_AppendToPostScript(psToken,
725 "8 /Helvetica SetFont\n",
726 "10 30 moveto\n",
727 "(Date: ", date, ") show\n",
728 "10 20 moveto\n",
729 "(File: ", fileName, ") show\n",
730 "10 10 moveto\n",
731 "(Created by: ", who, "@", Tcl_GetHostName(), ") show\n",
732 "0 0 moveto\n",
733 (char *)NULL);
734 }
735 /*
736 * Set the conversion from PostScript to X11 coordinates. Scale
737 * pica to pixels and flip the y-axis (the origin is the upperleft
738 * corner).
739 */
740 Blt_AppendToPostScript(psToken,
741 "% Transform coordinate system to use X11 coordinates\n\n",
742 "% 1. Flip y-axis over by reversing the scale,\n",
743 "% 2. Translate the origin to the other side of the page,\n",
744 "% making the origin the upper left corner\n", (char *)NULL);
745 Blt_FormatToPostScript(psToken, "%g -%g scale\n", xPixelsToPica,
746 yPixelsToPica);
747 /* Papersize is in pixels. Translate the new origin *after*
748 * changing the scale. */
749 Blt_FormatToPostScript(psToken, "0 %d translate\n\n",
750 -paperHeightPixels);
751 Blt_AppendToPostScript(psToken, "% User defined page layout\n\n",
752 "% Set color level\n", (char *)NULL);
753 Blt_FormatToPostScript(psToken, "/CL %d def\n\n", psPtr->colorMode);
754 Blt_FormatToPostScript(psToken, "%% Set origin\n%d %d translate\n\n",
755 psPtr->left, psPtr->bottom);
756 if (psPtr->landscape) {
757 Blt_FormatToPostScript(psToken,
758 "%% Landscape orientation\n0 %g translate\n-90 rotate\n",
759 ((double)graphPtr->width * psPtr->pageScale));
760 }
761 if (psPtr->pageScale != 1.0) {
762 Blt_AppendToPostScript(psToken, "\n% Setting graph scale factor\n",
763 (char *)NULL);
764 Blt_FormatToPostScript(psToken, " %g %g scale\n", psPtr->pageScale,
765 psPtr->pageScale);
766 }
767 Blt_AppendToPostScript(psToken, "\n%%EndSetup\n\n", (char *)NULL);
768 return TCL_OK;
769}
770
771
772static void
773MarginsToPostScript(graphPtr, psToken)
774 Graph *graphPtr;
775 PsToken psToken;
776{
777 PostScript *psPtr = (PostScript *)graphPtr->postscript;
778 XRectangle margin[4];
779
780 margin[0].x = margin[0].y = margin[3].x = margin[1].x = 0;
781 margin[0].width = margin[3].width = graphPtr->width;
782 margin[0].height = graphPtr->top;
783 margin[3].y = graphPtr->bottom;
784 margin[3].height = graphPtr->height - graphPtr->bottom;
785 margin[2].y = margin[1].y = graphPtr->top;
786 margin[1].width = graphPtr->left;
787 margin[2].height = margin[1].height = graphPtr->bottom - graphPtr->top;
788 margin[2].x = graphPtr->right;
789 margin[2].width = graphPtr->width - graphPtr->right;
790
791 /* Clear the surrounding margins and clip the plotting surface */
792 if (psPtr->decorations) {
793 Blt_BackgroundToPostScript(psToken,
794 Tk_3DBorderColor(graphPtr->border));
795 } else {
796 Blt_ClearBackgroundToPostScript(psToken);
797 }
798 Blt_RectanglesToPostScript(psToken, margin, 4);
799
800 /* Interior 3D border */
801 if ((psPtr->decorations) && (graphPtr->plotBorderWidth > 0)) {
802 int x, y, width, height;
803
804 x = graphPtr->left - graphPtr->plotBorderWidth;
805 y = graphPtr->top - graphPtr->plotBorderWidth;
806 width = (graphPtr->right - graphPtr->left) +
807 (2 * graphPtr->plotBorderWidth);
808 height = (graphPtr->bottom - graphPtr->top) +
809 (2 * graphPtr->plotBorderWidth);
810 Blt_Draw3DRectangleToPostScript(psToken, graphPtr->border,
811 (double)x, (double)y, width, height, graphPtr->plotBorderWidth,
812 graphPtr->plotRelief);
813 }
814 if (Blt_LegendSite(graphPtr->legend) & LEGEND_IN_MARGIN) {
815 /*
816 * Print the legend if we're using a site which lies in one
817 * of the margins (left, right, top, or bottom) of the graph.
818 */
819 Blt_LegendToPostScript(graphPtr->legend, psToken);
820 }
821 if (graphPtr->title != NULL) {
822 Blt_TextToPostScript(psToken, graphPtr->title,
823 &graphPtr->titleTextStyle, (double)graphPtr->titleX,
824 (double)graphPtr->titleY);
825 }
826 Blt_AxesToPostScript(graphPtr, psToken);
827}
828
829
830static int
831GraphToPostScript(graphPtr, ident, psToken)
832 Graph *graphPtr;
833 char *ident; /* Identifier string (usually the filename) */
834 PsToken psToken;
835{
836 int x, y, width, height;
837 int result;
838
839 /*
840 * We need to know how big a graph to print. If the graph hasn't
841 * been drawn yet, the width and height will be 1. Instead use
842 * the requested size of the widget. The user can still override
843 * this with the -width and -height postscript options.
844 */
845 if (graphPtr->height <= 1) {
846 graphPtr->height = Tk_ReqHeight(graphPtr->tkwin);
847 }
848 if (graphPtr->width <= 1) {
849 graphPtr->width = Tk_ReqWidth(graphPtr->tkwin);
850 }
851 result = PostScriptPreamble(graphPtr, ident, psToken);
852 if (result != TCL_OK) {
853 goto error;
854 }
855 /*
856 * Determine rectangle of the plotting area for the graph window
857 */
858 x = graphPtr->left - graphPtr->plotBorderWidth;
859 y = graphPtr->top - graphPtr->plotBorderWidth;
860
861 width = (graphPtr->right - graphPtr->left + 1) +
862 (2 * graphPtr->plotBorderWidth);
863 height = (graphPtr->bottom - graphPtr->top + 1) +
864 (2 * graphPtr->plotBorderWidth);
865
866 Blt_FontToPostScript(psToken, graphPtr->titleTextStyle.font);
867 Blt_RegionToPostScript(psToken, (double)x, (double)y, width, height);
868 if (graphPtr->postscript->decorations) {
869 Blt_BackgroundToPostScript(psToken, graphPtr->plotBg);
870 } else {
871 Blt_ClearBackgroundToPostScript(psToken);
872 }
873 Blt_AppendToPostScript(psToken, "Fill\n", (char *)NULL);
874 Blt_AppendToPostScript(psToken, "gsave clip\n\n", (char *)NULL);
875 /* Draw the grid, elements, and markers in the plotting area. */
876 if (!graphPtr->gridPtr->hidden) {
877 Blt_GridToPostScript(graphPtr, psToken);
878 }
879 Blt_MarkersToPostScript(graphPtr, psToken, TRUE);
880 if ((Blt_LegendSite(graphPtr->legend) & LEGEND_IN_PLOT) &&
881 (!Blt_LegendIsRaised(graphPtr->legend))) {
882 /* Print legend underneath elements and markers */
883 Blt_LegendToPostScript(graphPtr->legend, psToken);
884 }
885 Blt_AxisLimitsToPostScript(graphPtr, psToken);
886 Blt_ElementsToPostScript(graphPtr, psToken);
887 if ((Blt_LegendSite(graphPtr->legend) & LEGEND_IN_PLOT) &&
888 (Blt_LegendIsRaised(graphPtr->legend))) {
889 /* Print legend above elements (but not markers) */
890 Blt_LegendToPostScript(graphPtr->legend, psToken);
891 }
892 Blt_MarkersToPostScript(graphPtr, psToken, FALSE);
893 Blt_ActiveElementsToPostScript(graphPtr, psToken);
894 Blt_AppendToPostScript(psToken, "\n",
895 "% Unset clipping\n",
896 "grestore\n\n", (char *)NULL);
897 MarginsToPostScript(graphPtr, psToken);
898 Blt_AppendToPostScript(psToken,
899 "showpage\n",
900 "%Trailer\n",
901 "grestore\n",
902 "end\n",
903 "%EOF\n", (char *)NULL);
904 error:
905 /* Reset height and width of graph window */
906 graphPtr->width = Tk_Width(graphPtr->tkwin);
907 graphPtr->height = Tk_Height(graphPtr->tkwin);
908 graphPtr->flags = MAP_WORLD;
909
910 /*
911 * Redraw the graph in order to re-calculate the layout as soon as
912 * possible. This is in the case the crosshairs are active.
913 */
914 Blt_EventuallyRedrawGraph(graphPtr);
915 return result;
916}
917
918#ifdef WIN32
919
920static void
921InitAPMHeader(
922 Tk_Window tkwin,
923 int width, int height,
924 APMHEADER *headerPtr)
925{
926 unsigned int *p;
927 unsigned int sum;
928 Screen *screen;
929#define MM_INCH 25.4
930 double dpiX, dpiY;
931
932 headerPtr->key = 0x9ac6cdd7L;
933 headerPtr->hmf = 0;
934 headerPtr->inch = 1440;
935
936 screen = Tk_Screen(tkwin);
937 dpiX = (WidthOfScreen(screen) * MM_INCH) / WidthMMOfScreen(screen);
938 dpiY = (HeightOfScreen(screen) * MM_INCH) / HeightMMOfScreen(screen);
939
940 headerPtr->bbox.Left = headerPtr->bbox.Top = 0;
941 headerPtr->bbox.Bottom = (SHORT)((width * 1440) / dpiX);
942 headerPtr->bbox.Right = (SHORT)((height * 1440) / dpiY);
943 headerPtr->reserved = 0;
944 sum = 0;
945 for (p = (unsigned int *)headerPtr;
946 p < (unsigned int *)&(headerPtr->checksum); p++) {
947 sum ^= *p;
948 }
949 headerPtr->checksum = sum;
950}
951
952/*
953 * --------------------------------------------------------------------------
954 *
955 * CreateWindowEPS --
956 *
957 * Generates an EPS file with a Window metafile preview.
958 *
959 * Windows metafiles aren't very robust. Including exactly the
960 * same metafile (one embedded in a DOS EPS, the other as .wmf
961 * file) will play back differently.
962 *
963 * Results:
964 * None.
965 *
966 * --------------------------------------------------------------------------
967 */
968static int
969CreateWindowsEPS(
970 Graph *graphPtr,
971 PsToken psToken,
972 FILE *f)
973{
974 DWORD size;
975 DOSEPSHEADER epsHeader;
976 HANDLE hMem;
977 HDC hRefDC, hDC;
978 HENHMETAFILE hMetaFile;
979 Tcl_DString dString;
980 TkWinDC drawableDC;
981 TkWinDCState state;
982 int result;
983 unsigned char *buffer, *psBuffer;
984
985 Blt_AppendToPostScript(psToken, "\n", (char *)NULL);
986 psBuffer = Blt_PostScriptFromToken(psToken);
987 /*
988 * Fill out as much information as we can into the DOS EPS header.
989 * We won't know the start of the length of the WMF segment until
990 * we create the metafile.
991 */
992 epsHeader.magic[0] = 0xC5;
993 epsHeader.magic[1] = 0xD0;
994 epsHeader.magic[2] = 0xD3;
995 epsHeader.magic[3] = 0xC6;
996 epsHeader.psStart = sizeof(epsHeader);
997 epsHeader.psLength = strlen(psBuffer) + 1;
998 epsHeader.wmfStart = epsHeader.psStart + epsHeader.psLength;
999 epsHeader.wmfLength = 0L; /* Fill in later. */
1000 epsHeader.tiffStart = 0L;
1001 epsHeader.tiffLength = 0L;
1002 epsHeader.checksum = 0xFFFF;
1003
1004 result = TCL_ERROR;
1005 hRefDC = TkWinGetDrawableDC(graphPtr->display,
1006 Tk_WindowId(graphPtr->tkwin), &state);
1007
1008 /* Build a description string. */
1009 Tcl_DStringInit(&dString);
1010 Tcl_DStringAppend(&dString, "BLT Graph ", -1);
1011 Tcl_DStringAppend(&dString, BLT_VERSION, -1);
1012 Tcl_DStringAppend(&dString, "\0", -1);
1013 Tcl_DStringAppend(&dString, Tk_PathName(graphPtr->tkwin), -1);
1014 Tcl_DStringAppend(&dString, "\0", -1);
1015
1016 hDC = CreateEnhMetaFile(hRefDC, NULL, NULL, Tcl_DStringValue(&dString));
1017 Tcl_DStringFree(&dString);
1018
1019 if (hDC == NULL) {
1020 Tcl_AppendResult(graphPtr->interp, "can't create metafile: ",
1021 Blt_LastError(), (char *)NULL);
1022 return TCL_ERROR;
1023 }
1024 /* Assemble a Tk drawable that points to the metafile and let the
1025 * graph's drawing routine draw into it. */
1026 drawableDC.hdc = hDC;
1027 drawableDC.type = TWD_WINDC;
1028
1029 graphPtr->width = Tk_Width(graphPtr->tkwin);
1030 graphPtr->height = Tk_Height(graphPtr->tkwin);
1031 graphPtr->flags |= RESET_WORLD;
1032 Blt_LayoutGraph(graphPtr);
1033 Blt_DrawGraph(graphPtr, (Drawable)&drawableDC, FALSE);
1034 GdiFlush();
1035 hMetaFile = CloseEnhMetaFile(hDC);
1036
1037 size = GetWinMetaFileBits(hMetaFile, 0, NULL, MM_ANISOTROPIC, hRefDC);
1038 hMem = GlobalAlloc(GHND, size);
1039 if (hMem == NULL) {
1040 Tcl_AppendResult(graphPtr->interp, "can't allocate global memory:",
1041 Blt_LastError(), (char *)NULL);
1042 goto error;
1043 }
1044 buffer = (LPVOID)GlobalLock(hMem);
1045 if (!GetWinMetaFileBits(hMetaFile, size, buffer, MM_ANISOTROPIC, hRefDC)) {
1046 Tcl_AppendResult(graphPtr->interp, "can't get metafile data:",
1047 Blt_LastError(), (char *)NULL);
1048 goto error;
1049 }
1050
1051 /*
1052 * Fix up the EPS header with the correct metafile length and PS
1053 * offset (now that we what they are).
1054 */
1055 epsHeader.wmfLength = size;
1056 epsHeader.wmfStart = epsHeader.psStart + epsHeader.psLength;
1057
1058 /* Write out the eps header, */
1059 if (fwrite(&epsHeader, 1, sizeof(epsHeader), f) != sizeof(epsHeader)) {
1060 Tcl_AppendResult(graphPtr->interp, "error writing eps header:",
1061 Blt_LastError(), (char *)NULL);
1062 goto error;
1063 }
1064 /* the PostScript, */
1065 if (fwrite(psBuffer, 1, epsHeader.psLength, f) != epsHeader.psLength) {
1066 Tcl_AppendResult(graphPtr->interp, "error writing PostScript data:",
1067 Blt_LastError(), (char *)NULL);
1068 goto error;
1069 }
1070 /* and finally the metadata itself. */
1071 if (fwrite(buffer, 1, size, f) != size) {
1072 Tcl_AppendResult(graphPtr->interp, "error writing metafile data:",
1073 Blt_LastError(), (char *)NULL);
1074 goto error;
1075 }
1076 result = TCL_OK;
1077
1078 error:
1079 DeleteEnhMetaFile(hMetaFile);
1080 TkWinReleaseDrawableDC(Tk_WindowId(graphPtr->tkwin), hRefDC, &state);
1081 fclose(f);
1082 if (hMem != NULL) {
1083 GlobalUnlock(hMem);
1084 GlobalFree(hMem);
1085 }
1086 graphPtr->flags = MAP_WORLD;
1087 Blt_EventuallyRedrawGraph(graphPtr);
1088 return result;
1089}
1090
1091#endif /*WIN32*/
1092
1093/*
1094 *----------------------------------------------------------------------
1095 *
1096 * OutputOp --
1097 *
1098 * This procedure is invoked to print the graph in a file.
1099 *
1100 * Results:
1101 * Standard TCL result. TCL_OK if plot was successfully printed,
1102 * TCL_ERROR otherwise.
1103 *
1104 * Side effects:
1105 * A new PostScript file is created.
1106 *
1107 *----------------------------------------------------------------------
1108 */
1109static int
1110OutputOp(graphPtr, interp, argc, argv)
1111 Graph *graphPtr; /* Graph widget record */
1112 Tcl_Interp *interp;
1113 int argc; /* Number of options in argv vector */
1114 char **argv; /* Option vector */
1115{
1116 PostScript *psPtr = (PostScript *)graphPtr->postscript;
1117 FILE *f = NULL;
1118 PsToken psToken;
1119 char *fileName; /* Name of file to write PostScript output
1120 * If NULL, output is returned via
1121 * interp->result. */
1122 fileName = NULL;
1123 if (argc > 3) {
1124 if (argv[3][0] != '-') {
1125 fileName = argv[3]; /* First argument is the file name. */
1126 argv++, argc--;
1127 }
1128 if (Tk_ConfigureWidget(interp, graphPtr->tkwin, configSpecs, argc - 3,
1129 argv + 3, (char *)psPtr, TK_CONFIG_ARGV_ONLY) != TCL_OK) {
1130 return TCL_ERROR;
1131 }
1132 if (fileName != NULL) {
1133#ifdef WIN32
1134 f = fopen(fileName, "wb");
1135#else
1136 f = fopen(fileName, "w");
1137#endif
1138 if (f == NULL) {
1139 Tcl_AppendResult(interp, "can't create \"", fileName, "\": ",
1140 Tcl_PosixError(interp), (char *)NULL);
1141 return TCL_ERROR;
1142 }
1143 }
1144 }
1145 psToken = Blt_GetPsToken(graphPtr->interp, graphPtr->tkwin);
1146 psToken->fontVarName = psPtr->fontVarName;
1147 psToken->colorVarName = psPtr->colorVarName;
1148 psToken->colorMode = psPtr->colorMode;
1149
1150 if (GraphToPostScript(graphPtr, fileName, psToken) != TCL_OK) {
1151 goto error;
1152 }
1153 /*
1154 * If a file name was given, write the results to that file
1155 */
1156 if (f != NULL) {
1157#ifdef WIN32
1158 if ((psPtr->addPreview) && (psPtr->previewFormat != PS_PREVIEW_EPSI)) {
1159 if (CreateWindowsEPS(graphPtr, psToken, f)) {
1160 return TCL_ERROR;
1161 }
1162 } else {
1163 fputs(Blt_PostScriptFromToken(psToken), f);
1164 if (ferror(f)) {
1165 Tcl_AppendResult(interp, "error writing file \"", fileName,
1166 "\": ", Tcl_PosixError(interp), (char *)NULL);
1167 goto error;
1168 }
1169 }
1170#else
1171 fputs(Blt_PostScriptFromToken(psToken), f);
1172 if (ferror(f)) {
1173 Tcl_AppendResult(interp, "error writing file \"", fileName, "\": ",
1174 Tcl_PosixError(interp), (char *)NULL);
1175 goto error;
1176 }
1177#endif /* WIN32 */
1178 fclose(f);
1179 } else {
1180 Tcl_SetResult(interp, Blt_PostScriptFromToken(psToken), TCL_VOLATILE);
1181 }
1182 Blt_ReleasePsToken(psToken);
1183 return TCL_OK;
1184
1185 error:
1186 if (f != NULL) {
1187 fclose(f);
1188 }
1189 Blt_ReleasePsToken(psToken);
1190 return TCL_ERROR;
1191}
1192
1193/*
1194 *----------------------------------------------------------------------
1195 *
1196 * Blt_CreatePostScript --
1197 *
1198 * Creates a postscript structure.
1199 *
1200 * Results:
1201 * Always TCL_OK.
1202 *
1203 * Side effects:
1204 * A new PostScript structure is created.
1205 *
1206 *----------------------------------------------------------------------
1207 */
1208int
1209Blt_CreatePostScript(graphPtr)
1210 Graph *graphPtr;
1211{
1212 PostScript *psPtr;
1213
1214 psPtr = Blt_Calloc(1, sizeof(PostScript));
1215 assert(psPtr);
1216 psPtr->colorMode = PS_MODE_COLOR;
1217 psPtr->center = TRUE;
1218 psPtr->decorations = TRUE;
1219 graphPtr->postscript = psPtr;
1220
1221 if (Blt_ConfigureWidgetComponent(graphPtr->interp, graphPtr->tkwin,
1222 "postscript", "Postscript", configSpecs, 0, (char **)NULL,
1223 (char *)psPtr, 0) != TCL_OK) {
1224 return TCL_ERROR;
1225 }
1226 return TCL_OK;
1227}
1228
1229/*
1230 *--------------------------------------------------------------
1231 *
1232 * Blt_PostScriptOp --
1233 *
1234 * This procedure is invoked to process the Tcl command
1235 * that corresponds to a widget managed by this module.
1236 * See the user documentation for details on what it does.
1237 *
1238 * Results:
1239 * A standard Tcl result.
1240 *
1241 * Side effects:
1242 * See the user documentation.
1243 *
1244 *--------------------------------------------------------------
1245 */
1246static Blt_OpSpec psOps[] =
1247{
1248 {"cget", 2, (Blt_Op)CgetOp, 4, 4, "option",},
1249 {"configure", 2, (Blt_Op)ConfigureOp, 3, 0, "?option value?...",},
1250 {"output", 1, (Blt_Op)OutputOp, 3, 0,
1251 "?fileName? ?option value?...",},
1252};
1253
1254static int nPsOps = sizeof(psOps) / sizeof(Blt_OpSpec);
1255
1256int
1257Blt_PostScriptOp(graphPtr, interp, argc, argv)
1258 Graph *graphPtr; /* Graph widget record */
1259 Tcl_Interp *interp;
1260 int argc; /* # arguments */
1261 char **argv; /* Argument list */
1262{
1263 Blt_Op proc;
1264 int result;
1265
1266 proc = Blt_GetOp(interp, nPsOps, psOps, BLT_OP_ARG2, argc, argv, 0);
1267 if (proc == NULL) {
1268 return TCL_ERROR;
1269 }
1270 result = (*proc) (graphPtr, interp, argc, argv);
1271 return result;
1272}
1273
Note: See TracBrowser for help on using the repository browser.