diff options
Diffstat (limited to 'generic/tkCanvPs.c')
-rw-r--r-- | generic/tkCanvPs.c | 504 |
1 files changed, 400 insertions, 104 deletions
diff --git a/generic/tkCanvPs.c b/generic/tkCanvPs.c index 4c99b15..c234320 100644 --- a/generic/tkCanvPs.c +++ b/generic/tkCanvPs.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCanvPs.c,v 1.5 1999/04/16 01:51:11 stanton Exp $ + * RCS: @(#) $Id: tkCanvPs.c,v 1.6 1999/12/14 06:52:26 hobbs Exp $ */ #include "tkInt.h" @@ -68,6 +68,8 @@ typedef struct TkPostscriptInfo { * the pre-pass that collects font information, * so the Postscript generated isn't * relevant. */ + int prolog; /* Non-zero means output should contain + the file prolog.ps in the header. */ } TkPostscriptInfo; /* @@ -99,6 +101,8 @@ static Tk_ConfigSpec configSpecs[] = { "", Tk_Offset(TkPostscriptInfo, pageXString), 0}, {TK_CONFIG_STRING, "-pagey", (char *) NULL, (char *) NULL, "", Tk_Offset(TkPostscriptInfo, pageYString), 0}, + {TK_CONFIG_BOOLEAN, "-prolog", (char *) NULL, (char *) NULL, + "", Tk_Offset(TkPostscriptInfo, prolog), 0}, {TK_CONFIG_BOOLEAN, "-rotate", (char *) NULL, (char *) NULL, "", Tk_Offset(TkPostscriptInfo, rotate), 0}, {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL, @@ -124,7 +128,7 @@ static CONST char * CONST prolog[]= { \n\ % This is a standard prolog for Postscript generated by Tk's canvas\n\ % widget.\n\ -% RCS: @(#) $Id: tkCanvPs.c,v 1.5 1999/04/16 01:51:11 stanton Exp $\n\ +% RCS: @(#) $Id: tkCanvPs.c,v 1.6 1999/12/14 06:52:26 hobbs Exp $\n\ \n\ % The definitions below just define all of the variables used in\n\ % any of the procedures here. This is needed for obscure reasons\n\ @@ -461,13 +465,15 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) * to know that argv[1] is * "postscript". */ { - TkPostscriptInfo psInfo, *oldInfoPtr; + TkPostscriptInfo psInfo; + Tk_PostscriptInfo oldInfoPtr; int result; Tk_Item *itemPtr; #define STRING_LENGTH 400 char string[STRING_LENGTH+1], *p; time_t now; size_t length; + Tk_Window tkwin = canvasPtr->tkwin; int deltaX = 0, deltaY = 0; /* Offset of lower-left corner of * area to be marked up, measured * in canvas units from the positioning @@ -487,8 +493,8 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) *---------------------------------------------------------------- */ - oldInfoPtr = canvasPtr->psInfoPtr; - canvasPtr->psInfoPtr = &psInfo; + oldInfoPtr = canvasPtr->psInfo; + canvasPtr->psInfo = (Tk_PostscriptInfo) &psInfo; psInfo.x = canvasPtr->xOrigin; psInfo.y = canvasPtr->yOrigin; psInfo.width = -1; @@ -510,8 +516,9 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) psInfo.channelName = NULL; psInfo.chan = NULL; psInfo.prepass = 0; + psInfo.prolog = 1; Tcl_InitHashTable(&psInfo.fontTable, TCL_STRING_KEYS); - result = Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin, + result = Tk_ConfigureWidget(interp, tkwin, configSpecs, argc-2, argv+2, (char *) &psInfo, TK_CONFIG_ARGV_ONLY); if (result != TCL_OK) { @@ -519,41 +526,41 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) } if (psInfo.width == -1) { - psInfo.width = Tk_Width(canvasPtr->tkwin); + psInfo.width = Tk_Width(tkwin); } if (psInfo.height == -1) { - psInfo.height = Tk_Height(canvasPtr->tkwin); + psInfo.height = Tk_Height(tkwin); } psInfo.x2 = psInfo.x + psInfo.width; psInfo.y2 = psInfo.y + psInfo.height; if (psInfo.pageXString != NULL) { - if (GetPostscriptPoints(canvasPtr->interp, psInfo.pageXString, + if (GetPostscriptPoints(interp, psInfo.pageXString, &psInfo.pageX) != TCL_OK) { goto cleanup; } } if (psInfo.pageYString != NULL) { - if (GetPostscriptPoints(canvasPtr->interp, psInfo.pageYString, + if (GetPostscriptPoints(interp, psInfo.pageYString, &psInfo.pageY) != TCL_OK) { goto cleanup; } } if (psInfo.pageWidthString != NULL) { - if (GetPostscriptPoints(canvasPtr->interp, psInfo.pageWidthString, + if (GetPostscriptPoints(interp, psInfo.pageWidthString, &psInfo.scale) != TCL_OK) { goto cleanup; } psInfo.scale /= psInfo.width; } else if (psInfo.pageHeightString != NULL) { - if (GetPostscriptPoints(canvasPtr->interp, psInfo.pageHeightString, + if (GetPostscriptPoints(interp, psInfo.pageHeightString, &psInfo.scale) != TCL_OK) { goto cleanup; } psInfo.scale /= psInfo.height; } else { - psInfo.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(canvasPtr->tkwin)); - psInfo.scale /= WidthOfScreen(Tk_Screen(canvasPtr->tkwin)); + psInfo.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(tkwin)); + psInfo.scale /= WidthOfScreen(Tk_Screen(tkwin)); } switch (psInfo.pageAnchor) { case TK_ANCHOR_NW: @@ -601,7 +608,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) } else if (strncmp(psInfo.colorMode, "color", length) == 0) { psInfo.colorLevel = 2; } else { - Tcl_AppendResult(canvasPtr->interp, "bad color mode \"", + Tcl_AppendResult(interp, "bad color mode \"", psInfo.colorMode, "\": must be monochrome, ", "gray, or color", (char *) NULL); goto cleanup; @@ -615,7 +622,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) */ if (psInfo.channelName != NULL) { - Tcl_AppendResult(canvasPtr->interp, "can't specify both -file", + Tcl_AppendResult(interp, "can't specify both -file", " and -channel", (char *) NULL); result = TCL_ERROR; goto cleanup; @@ -626,18 +633,18 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) * the -file specification. */ - if (Tcl_IsSafe(canvasPtr->interp)) { - Tcl_AppendResult(canvasPtr->interp, "can't specify -file in a", + if (Tcl_IsSafe(interp)) { + Tcl_AppendResult(interp, "can't specify -file in a", " safe interpreter", (char *) NULL); result = TCL_ERROR; goto cleanup; } - p = Tcl_TranslateFileName(canvasPtr->interp, psInfo.fileName, &buffer); + p = Tcl_TranslateFileName(interp, psInfo.fileName, &buffer); if (p == NULL) { goto cleanup; } - psInfo.chan = Tcl_OpenFileChannel(canvasPtr->interp, p, "w", 0666); + psInfo.chan = Tcl_OpenFileChannel(interp, p, "w", 0666); Tcl_DStringFree(&buffer); if (psInfo.chan == NULL) { goto cleanup; @@ -652,14 +659,14 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) * is open for writing. */ - psInfo.chan = Tcl_GetChannel(canvasPtr->interp, psInfo.channelName, + psInfo.chan = Tcl_GetChannel(interp, psInfo.channelName, &mode); if (psInfo.chan == (Tcl_Channel) NULL) { result = TCL_ERROR; goto cleanup; } if ((mode & TCL_WRITABLE) == 0) { - Tcl_AppendResult(canvasPtr->interp, "channel \"", + Tcl_AppendResult(interp, "channel \"", psInfo.channelName, "\" wasn't opened for writing", (char *) NULL); result = TCL_ERROR; @@ -687,9 +694,9 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) if (itemPtr->typePtr->postscriptProc == NULL) { continue; } - result = (*itemPtr->typePtr->postscriptProc)(canvasPtr->interp, + result = (*itemPtr->typePtr->postscriptProc)(interp, (Tk_Canvas) canvasPtr, itemPtr, 1); - Tcl_ResetResult(canvasPtr->interp); + Tcl_ResetResult(interp); if (result != TCL_OK) { /* * An error just occurred. Just skip out of this loop. @@ -709,21 +716,22 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) *-------------------------------------------------------- */ - Tcl_AppendResult(canvasPtr->interp, "%!PS-Adobe-3.0 EPSF-3.0\n", + if (psInfo.prolog) { + Tcl_AppendResult(interp, "%!PS-Adobe-3.0 EPSF-3.0\n", "%%Creator: Tk Canvas Widget\n", (char *) NULL); #ifdef HAVE_PW_GECOS if (!Tcl_IsSafe(interp)) { struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */ - Tcl_AppendResult(canvasPtr->interp, "%%For: ", + Tcl_AppendResult(interp, "%%For: ", (pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n", (char *) NULL); endpwent(); } #endif /* HAVE_PW_GECOS */ - Tcl_AppendResult(canvasPtr->interp, "%%Title: Window ", - Tk_PathName(canvasPtr->tkwin), "\n", (char *) NULL); + Tcl_AppendResult(interp, "%%Title: Window ", + Tk_PathName(tkwin), "\n", (char *) NULL); time(&now); - Tcl_AppendResult(canvasPtr->interp, "%%CreationDate: ", + Tcl_AppendResult(interp, "%%CreationDate: ", ctime(&now), (char *) NULL); /* INTL: Native. */ if (!psInfo.rotate) { sprintf(string, "%d %d %d %d", @@ -741,21 +749,21 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) (int) (psInfo.pageY + psInfo.scale*(deltaX + psInfo.width) + 1.0)); } - Tcl_AppendResult(canvasPtr->interp, "%%BoundingBox: ", string, + Tcl_AppendResult(interp, "%%BoundingBox: ", string, "\n", (char *) NULL); - Tcl_AppendResult(canvasPtr->interp, "%%Pages: 1\n", + Tcl_AppendResult(interp, "%%Pages: 1\n", "%%DocumentData: Clean7Bit\n", (char *) NULL); - Tcl_AppendResult(canvasPtr->interp, "%%Orientation: ", + Tcl_AppendResult(interp, "%%Orientation: ", psInfo.rotate ? "Landscape\n" : "Portrait\n", (char *) NULL); p = "%%DocumentNeededResources: font "; for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - Tcl_AppendResult(canvasPtr->interp, p, + Tcl_AppendResult(interp, p, Tcl_GetHashKey(&psInfo.fontTable, hPtr), "\n", (char *) NULL); p = "%%+ font "; } - Tcl_AppendResult(canvasPtr->interp, "%%EndComments\n\n", (char *) NULL); + Tcl_AppendResult(interp, "%%EndComments\n\n", (char *) NULL); /* * Insert the prolog @@ -765,7 +773,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) } if (psInfo.chan != NULL) { - Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1); + Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); Tcl_ResetResult(canvasPtr->interp); } @@ -776,14 +784,14 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) */ sprintf(string, "/CL %d def\n", psInfo.colorLevel); - Tcl_AppendResult(canvasPtr->interp, "%%BeginSetup\n", string, + Tcl_AppendResult(interp, "%%BeginSetup\n", string, (char *) NULL); for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - Tcl_AppendResult(canvasPtr->interp, "%%IncludeResource: font ", + Tcl_AppendResult(interp, "%%IncludeResource: font ", Tcl_GetHashKey(&psInfo.fontTable, hPtr), "\n", (char *) NULL); } - Tcl_AppendResult(canvasPtr->interp, "%%EndSetup\n\n", (char *) NULL); + Tcl_AppendResult(interp, "%%EndSetup\n\n", (char *) NULL); /* *----------------------------------------------------------- @@ -793,26 +801,31 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) *----------------------------------------------------------- */ - Tcl_AppendResult(canvasPtr->interp, "%%Page: 1 1\n", "save\n", + Tcl_AppendResult(interp, "%%Page: 1 1\n", "save\n", (char *) NULL); sprintf(string, "%.1f %.1f translate\n", psInfo.pageX, psInfo.pageY); - Tcl_AppendResult(canvasPtr->interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, (char *) NULL); if (psInfo.rotate) { - Tcl_AppendResult(canvasPtr->interp, "90 rotate\n", (char *) NULL); + Tcl_AppendResult(interp, "90 rotate\n", (char *) NULL); } sprintf(string, "%.4g %.4g scale\n", psInfo.scale, psInfo.scale); - Tcl_AppendResult(canvasPtr->interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, (char *) NULL); sprintf(string, "%d %d translate\n", deltaX - psInfo.x, deltaY); - Tcl_AppendResult(canvasPtr->interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, (char *) NULL); sprintf(string, "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g", - psInfo.x, Tk_CanvasPsY((Tk_Canvas) canvasPtr, (double) psInfo.y), - psInfo.x2, Tk_CanvasPsY((Tk_Canvas) canvasPtr, (double) psInfo.y), - psInfo.x2, Tk_CanvasPsY((Tk_Canvas) canvasPtr, (double) psInfo.y2), - psInfo.x, Tk_CanvasPsY((Tk_Canvas) canvasPtr, (double) psInfo.y2)); - Tcl_AppendResult(canvasPtr->interp, string, + psInfo.x, + Tk_PostscriptY((double) psInfo.y, (Tk_PostscriptInfo) &psInfo), + psInfo.x2, + Tk_PostscriptY((double) psInfo.y, (Tk_PostscriptInfo) &psInfo), + psInfo.x2, + Tk_PostscriptY((double) psInfo.y2, (Tk_PostscriptInfo) &psInfo), + psInfo.x, + Tk_PostscriptY((double) psInfo.y2, (Tk_PostscriptInfo) &psInfo)); + Tcl_AppendResult(interp, string, " lineto closepath clip newpath\n", (char *) NULL); + } if (psInfo.chan != NULL) { - Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1); + Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); Tcl_ResetResult(canvasPtr->interp); } @@ -833,21 +846,24 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) if (itemPtr->typePtr->postscriptProc == NULL) { continue; } - Tcl_AppendResult(canvasPtr->interp, "gsave\n", (char *) NULL); - result = (*itemPtr->typePtr->postscriptProc)(canvasPtr->interp, + if (itemPtr->state == TK_STATE_HIDDEN) { + continue; + } + Tcl_AppendResult(interp, "gsave\n", (char *) NULL); + result = (*itemPtr->typePtr->postscriptProc)(interp, (Tk_Canvas) canvasPtr, itemPtr, 0); if (result != TCL_OK) { char msg[64 + TCL_INTEGER_SPACE]; sprintf(msg, "\n (generating Postscript for item %d)", itemPtr->id); - Tcl_AddErrorInfo(canvasPtr->interp, msg); + Tcl_AddErrorInfo(interp, msg); goto cleanup; } - Tcl_AppendResult(canvasPtr->interp, "grestore\n", (char *) NULL); + Tcl_AppendResult(interp, "grestore\n", (char *) NULL); if (psInfo.chan != NULL) { - Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1); - Tcl_ResetResult(canvasPtr->interp); + Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); + Tcl_ResetResult(interp); } } @@ -858,10 +874,12 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) *--------------------------------------------------------------------- */ - Tcl_AppendResult(canvasPtr->interp, "restore showpage\n\n", + if (psInfo.prolog) { + Tcl_AppendResult(interp, "restore showpage\n\n", "%%Trailer\nend\n%%EOF\n", (char *) NULL); + } if (psInfo.chan != NULL) { - Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1); + Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); Tcl_ResetResult(canvasPtr->interp); } @@ -895,20 +913,20 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) ckfree(psInfo.fileName); } if ((psInfo.chan != NULL) && (psInfo.channelName == NULL)) { - Tcl_Close(canvasPtr->interp, psInfo.chan); + Tcl_Close(interp, psInfo.chan); } if (psInfo.channelName != NULL) { ckfree(psInfo.channelName); } Tcl_DeleteHashTable(&psInfo.fontTable); - canvasPtr->psInfoPtr = oldInfoPtr; + canvasPtr->psInfo = (Tk_PostscriptInfo) oldInfoPtr; return result; } /* *-------------------------------------------------------------- * - * Tk_CanvasPsColor -- + * Tk_PostscriptColor -- * * This procedure is called by individual canvas items when * they want to set a color value for output. Given information @@ -928,14 +946,12 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) */ int -Tk_CanvasPsColor(interp, canvas, colorPtr) - Tcl_Interp *interp; /* Interpreter for returning Postscript - * or error message. */ - Tk_Canvas canvas; /* Information about canvas. */ +Tk_PostscriptColor(interp, psInfo, colorPtr) + Tcl_Interp *interp; + Tk_PostscriptInfo psInfo; /* Postscript info. */ XColor *colorPtr; /* Information about color. */ { - TkCanvas *canvasPtr = (TkCanvas *) canvas; - TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr; + TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; int tmp; double red, green, blue; char string[200]; @@ -989,7 +1005,7 @@ Tk_CanvasPsColor(interp, canvas, colorPtr) /* *-------------------------------------------------------------- * - * Tk_CanvasPsFont -- + * Tk_PostscriptFont -- * * This procedure is called by individual canvas items when * they want to output text. Given information about an X @@ -1010,15 +1026,13 @@ Tk_CanvasPsColor(interp, canvas, colorPtr) */ int -Tk_CanvasPsFont(interp, canvas, tkfont) - Tcl_Interp *interp; /* Interpreter for returning Postscript - * or error message. */ - Tk_Canvas canvas; /* Information about canvas. */ +Tk_PostscriptFont(interp, psInfo, tkfont) + Tcl_Interp *interp; + Tk_PostscriptInfo psInfo; /* Postscript Info. */ Tk_Font tkfont; /* Information about font in which text * is to be printed. */ { - TkCanvas *canvasPtr = (TkCanvas *) canvas; - TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr; + TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; char *end; char pointString[TCL_INTEGER_SPACE]; Tcl_DString ds; @@ -1083,7 +1097,7 @@ Tk_CanvasPsFont(interp, canvas, tkfont) /* *-------------------------------------------------------------- * - * Tk_CanvasPsBitmap -- + * Tk_PostscriptBitmap -- * * This procedure is called to output the contents of a * sub-region of a bitmap in proper image data format for @@ -1103,18 +1117,18 @@ Tk_CanvasPsFont(interp, canvas, tkfont) */ int -Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height) - Tcl_Interp *interp; /* Interpreter for returning Postscript - * or error message. */ - Tk_Canvas canvas; /* Information about canvas. */ +Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, startX, startY, width, + height) + Tcl_Interp *interp; + Tk_Window tkwin; + Tk_PostscriptInfo psInfo; /* Postscript info. */ Pixmap bitmap; /* Bitmap for which to generate * Postscript. */ int startX, startY; /* Coordinates of upper-left corner * of rectangular region to output. */ int width, height; /* Height of rectangular region. */ { - TkCanvas *canvasPtr = (TkCanvas *) canvas; - TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr; + TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; XImage *imagePtr; int charsInLine, x, y, lastX, lastY, value, mask; unsigned int totalWidth, totalHeight; @@ -1135,10 +1149,10 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height) * it shouldn't matter here. */ - XGetGeometry(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap, &dummyRoot, + XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot, (int *) &dummyX, (int *) &dummyY, (unsigned int *) &totalWidth, (unsigned int *) &totalHeight, &dummyBorderwidth, &dummyDepth); - imagePtr = XGetImage(Tk_Display(canvasPtr->tkwin), bitmap, 0, 0, + imagePtr = XGetImage(Tk_Display(tkwin), bitmap, 0, 0, totalWidth, totalHeight, 1, XYPixmap); Tcl_AppendResult(interp, "<", (char *) NULL); mask = 0x80; @@ -1180,7 +1194,7 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height) /* *-------------------------------------------------------------- * - * Tk_CanvasPsStipple -- + * Tk_PostscriptStipple -- * * This procedure is called by individual canvas items when * they have created a path that they'd like to be filled with @@ -1202,14 +1216,14 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height) */ int -Tk_CanvasPsStipple(interp, canvas, bitmap) - Tcl_Interp *interp; /* Interpreter for returning Postscript +Tk_PostscriptStipple(interp, tkwin, psInfo, bitmap) + Tcl_Interp *interp; + Tk_Window tkwin; + Tk_PostscriptInfo psInfo; /* Interpreter for returning Postscript * or error message. */ - Tk_Canvas canvas; /* Information about canvas. */ Pixmap bitmap; /* Bitmap to use for stippling. */ { - TkCanvas *canvasPtr = (TkCanvas *) canvas; - TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr; + TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; int width, height; char string[TCL_INTEGER_SPACE * 2]; Window dummyRoot; @@ -1228,12 +1242,12 @@ Tk_CanvasPsStipple(interp, canvas, bitmap) * it shouldn't matter here. */ - XGetGeometry(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap, &dummyRoot, + XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot, (int *) &dummyX, (int *) &dummyY, (unsigned *) &width, (unsigned *) &height, &dummyBorderwidth, &dummyDepth); sprintf(string, "%d %d ", width, height); Tcl_AppendResult(interp, string, (char *) NULL); - if (Tk_CanvasPsBitmap(interp, (Tk_Canvas) canvasPtr, bitmap, 0, 0, + if (Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, 0, 0, width, height) != TCL_OK) { return TCL_ERROR; } @@ -1244,9 +1258,9 @@ Tk_CanvasPsStipple(interp, canvas, bitmap) /* *-------------------------------------------------------------- * - * Tk_CanvasPsY -- + * Tk_PostscriptY -- * - * Given a y-coordinate in canvas coordinates, this procedure + * Given a y-coordinate in local coordinates, this procedure * returns a y-coordinate to use for Postscript output. * * Results: @@ -1260,12 +1274,11 @@ Tk_CanvasPsStipple(interp, canvas, bitmap) */ double -Tk_CanvasPsY(canvas, y) - Tk_Canvas canvas; /* Token for canvas on whose behalf - * Postscript is being generated. */ +Tk_PostscriptY(y, psInfo) double y; /* Y-coordinate in canvas coords. */ + Tk_PostscriptInfo psInfo; /* Postscript info */ { - TkPostscriptInfo *psInfoPtr = ((TkCanvas *) canvas)->psInfoPtr; + TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; return psInfoPtr->y2 - y; } @@ -1273,7 +1286,7 @@ Tk_CanvasPsY(canvas, y) /* *-------------------------------------------------------------- * - * Tk_CanvasPsPath -- + * Tk_PostscriptPath -- * * Given an array of points for a path, generate Postscript * commands to create the path. @@ -1288,29 +1301,28 @@ Tk_CanvasPsY(canvas, y) */ void -Tk_CanvasPsPath(interp, canvas, coordPtr, numPoints) - Tcl_Interp *interp; /* Put generated Postscript in this - * interpreter's result field. */ - Tk_Canvas canvas; /* Canvas on whose behalf Postscript +Tk_PostscriptPath(interp, psInfo, coordPtr, numPoints) + Tcl_Interp *interp; + Tk_PostscriptInfo psInfo; /* Canvas on whose behalf Postscript * is being generated. */ double *coordPtr; /* Pointer to first in array of * 2*numPoints coordinates giving * points for path. */ int numPoints; /* Number of points at *coordPtr. */ { - TkPostscriptInfo *psInfoPtr = ((TkCanvas *) canvas)->psInfoPtr; + TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; char buffer[200]; if (psInfoPtr->prepass) { return; } sprintf(buffer, "%.15g %.15g moveto\n", coordPtr[0], - Tk_CanvasPsY(canvas, coordPtr[1])); + Tk_PostscriptY(coordPtr[1], psInfo)); Tcl_AppendResult(interp, buffer, (char *) NULL); for (numPoints--, coordPtr += 2; numPoints > 0; numPoints--, coordPtr += 2) { sprintf(buffer, "%.15g %.15g lineto\n", coordPtr[0], - Tk_CanvasPsY(canvas, coordPtr[1])); + Tk_PostscriptY(coordPtr[1], psInfo)); Tcl_AppendResult(interp, buffer, (char *) NULL); } } @@ -1385,3 +1397,287 @@ GetPostscriptPoints(interp, string, doublePtr) *doublePtr = d; return TCL_OK; } + +/* + *-------------------------------------------------------------- + * + * TkImageGetColor -- + * + * This procedure converts a pixel value to three floating + * point numbers, representing the amount of red, green, and + * blue in that pixel on the screen. It makes use of colormap + * data passed as an argument, and should work for all Visual + * types. + * + * Results: + * Returns red, green, and blue color values in the range + * 0 to 1. There are no error returns. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +TkImageGetColor(cdata, pixel, red, green, blue) + TkColormapData *cdata; /* Colormap data */ + unsigned long pixel; /* Pixel value to look up */ + double *red, *green, *blue; /* Color data to return */ +{ + if (cdata->separated) { + int r = (pixel & cdata->red_mask) >> cdata->red_shift; + int g = (pixel & cdata->green_mask) >> cdata->green_shift; + int b = (pixel & cdata->blue_mask) >> cdata->blue_shift; + *red = cdata->colors[r].red / 65535.0; + *green = cdata->colors[g].green / 65535.0; + *blue = cdata->colors[b].blue / 65535.0; + } else { + *red = cdata->colors[pixel].red / 65535.0; + *green = cdata->colors[pixel].green / 65535.0; + *blue = cdata->colors[pixel].blue / 65535.0; + } +} + +/* + *-------------------------------------------------------------- + * + * TkPostscriptImage -- + * + * This procedure is called to output the contents of an + * image in Postscript, using a format appropriate for the + * current color mode (i.e. one bit per pixel in monochrome, + * one byte per pixel in gray, and three bytes per pixel in + * color). + * + * Results: + * Returns a standard Tcl return value. If an error occurs + * then an error message will be left in interp->result. + * If no error occurs, then additional Postscript will be + * appended to interp->result. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +int +TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height) + Tcl_Interp *interp; + Tk_Window tkwin; + Tk_PostscriptInfo psInfo; /* postscript info */ + XImage *ximage; /* Image to draw */ + int x, y; /* First pixel to output */ + int width, height; /* Width and height of area */ +{ + TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; + char buffer[256]; + int xx, yy, band, maxRows; + double red, green, blue; + int bytesPerLine=0, maxWidth=0; + int level = psInfoPtr->colorLevel; + Colormap cmap; + int i, depth, ncolors; + Visual *visual; + TkColormapData cdata; + + if (psInfoPtr->prepass) { + return TCL_OK; + } + + cmap = Tk_Colormap(tkwin); + depth = Tk_Depth(tkwin); + visual = Tk_Visual(tkwin); + + /* + * Obtain information about the colormap, ie the mapping between + * pixel values and RGB values. The code below should work + * for all Visual types. + */ + + ncolors = visual->map_entries; + cdata.colors = (XColor *) ckalloc(sizeof(XColor) * ncolors); + cdata.ncolors = ncolors; + + if (visual->class == DirectColor || visual->class == TrueColor) { + cdata.separated = 1; + cdata.red_mask = visual->red_mask; + cdata.green_mask = visual->green_mask; + cdata.blue_mask = visual->blue_mask; + cdata.red_shift = 0; + cdata.green_shift = 0; + cdata.blue_shift = 0; + while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) + cdata.red_shift ++; + while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) + cdata.green_shift ++; + while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) + cdata.blue_shift ++; + for (i = 0; i < ncolors; i ++) + cdata.colors[i].pixel = + ((i << cdata.red_shift) & cdata.red_mask) | + ((i << cdata.green_shift) & cdata.green_mask) | + ((i << cdata.blue_shift) & cdata.blue_mask); + } else { + cdata.separated=0; + for (i = 0; i < ncolors; i ++) + cdata.colors[i].pixel = i; + } + if (visual->class == StaticGray || visual->class == GrayScale) + cdata.color = 0; + else + cdata.color = 1; + + + XQueryColors(Tk_Display(tkwin), cmap, cdata.colors, ncolors); + + /* + * Figure out which color level to use (possibly lower than the + * one specified by the user). For example, if the user specifies + * color with monochrome screen, use gray or monochrome mode instead. + */ + + if (!cdata.color && level == 2) { + level = 1; + } + + if (!cdata.color && cdata.ncolors == 2) { + level = 0; + } + + /* + * Check that at least one row of the image can be represented + * with a string less than 64 KB long (this is a limit in the + * Postscript interpreter). + */ + + switch (level) + { + case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break; + case 1: bytesPerLine = width; maxWidth = 60000; break; + case 2: bytesPerLine = 3 * width; maxWidth = 20000; break; + } + + if (bytesPerLine > 60000) { + Tcl_ResetResult(interp); + sprintf(buffer, + "Can't generate Postscript for images more than %d pixels wide", + maxWidth); + Tcl_AppendResult(interp, buffer, (char *) NULL); + ckfree((char *) cdata.colors); + return TCL_ERROR; + } + + maxRows = 60000 / bytesPerLine; + + for (band = height-1; band >= 0; band -= maxRows) { + int rows = (band >= maxRows) ? maxRows : band + 1; + int lineLen = 0; + switch (level) { + case 0: + sprintf(buffer, "%d %d 1 matrix {\n<", width, rows); + Tcl_AppendResult(interp, buffer, (char *) NULL); + break; + case 1: + sprintf(buffer, "%d %d 8 matrix {\n<", width, rows); + Tcl_AppendResult(interp, buffer, (char *) NULL); + break; + case 2: + sprintf(buffer, "%d %d 8 matrix {\n<", + width, rows); + Tcl_AppendResult(interp, buffer, (char *) NULL); + break; + } + for (yy = band; yy > band - rows; yy--) { + switch (level) { + case 0: { + /* + * Generate data for image in monochrome mode. + * No attempt at dithering is made--instead, just + * set a threshold. + */ + unsigned char mask=0x80; + unsigned char data=0x00; + for (xx = x; xx< x+width; xx++) { + TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), + &red, &green, &blue); + if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5) + data |= mask; + mask >>= 1; + if (mask == 0) { + sprintf(buffer, "%02X", data); + Tcl_AppendResult(interp, buffer, (char *) NULL); + lineLen += 2; + if (lineLen > 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", (char *) NULL); + } + mask=0x80; + data=0x00; + } + } + if ((width % 8) != 0) { + sprintf(buffer, "%02X", data); + Tcl_AppendResult(interp, buffer, (char *) NULL); + mask=0x80; + data=0x00; + } + break; + } + case 1: { + /* + * Generate data in gray mode--in this case, take a + * weighted sum of the red, green, and blue values. + */ + for (xx = x; xx < x+width; xx ++) { + TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), + &red, &green, &blue); + sprintf(buffer, "%02X", (int) floor(0.5 + 255.0 * + (0.30 * red + + 0.59 * green + + 0.11 * blue))); + Tcl_AppendResult(interp, buffer, (char *) NULL); + lineLen += 2; + if (lineLen > 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", (char *) NULL); + } + } + break; + } + case 2: { + /* + * Finally, color mode. Here, just output the red, green, + * and blue values directly. + */ + for (xx = x; xx < x+width; xx++) { + TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), + &red, &green, &blue); + sprintf(buffer, "%02X%02X%02X", + (int) floor(0.5 + 255.0 * red), + (int) floor(0.5 + 255.0 * green), + (int) floor(0.5 + 255.0 * blue)); + Tcl_AppendResult(interp, buffer, (char *) NULL); + lineLen += 6; + if (lineLen > 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", (char *) NULL); + } + } + break; + } + } + } + switch (level) { + case 0: sprintf(buffer, ">\n} image\n"); break; + case 1: sprintf(buffer, ">\n} image\n"); break; + case 2: sprintf(buffer, ">\n} false 3 colorimage\n"); break; + } + Tcl_AppendResult(interp, buffer, (char *) NULL); + sprintf(buffer, "0 %d translate\n", rows); + Tcl_AppendResult(interp, buffer, (char *) NULL); + } + ckfree((char *) cdata.colors); + return TCL_OK; +} |