static int CanvasPsWindow( Tcl_Interp *interp, /* Leave Postscript or error message here. */ Tk_Window tkwin, /* window to be printed */ Tk_Canvas canvas, /* Information about overall canvas. */ double x, double y, /* origin of window. */ int width, int height) /* width/height of window. */ { XImage *ximage; int result; #ifdef X_GetImage Tk_ErrorHandler handle; #endif Tcl_Obj *cmdObj, *psObj; Tcl_InterpState interpState = Tcl_SaveInterpState(interp, TCL_OK); /* * Locate the subwindow within the wider window. */ psObj = Tcl_ObjPrintf( "\n%%%% %s item (%s, %d x %d)\n" /* Comment */ "%.15g %.15g translate\n", /* Position */ Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y); /* * First try if the widget has its own "postscript" command. If it exists, * this will produce much better postscript than when a pixmap is used. */ Tcl_ResetResult(interp); cmdObj = Tcl_ObjPrintf("%s postscript -prolog 0", Tk_PathName(tkwin)); Tcl_IncrRefCount(cmdObj); result = Tcl_EvalObjEx(interp, cmdObj, 0); Tcl_DecrRefCount(cmdObj); if (result == TCL_OK) { Tcl_AppendPrintfToObj(psObj, "50 dict begin\nsave\ngsave\n" "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d 0 rlineto closepath\n" "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n", height, width, height, width); Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); Tcl_AppendToObj(psObj, "\nrestore\nend\n\n\n", -1); goto done; } /* * If the window is off the screen it will generate a BadMatch/XError. We * catch any BadMatch errors here */ #ifdef X_GetImage handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch, X_GetImage, -1, xerrorhandler, tkwin); #endif /* * Generate an XImage from the window. We can then read pixel values out * of the XImage. */ ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0, (unsigned) width, (unsigned) height, AllPlanes, ZPixmap); #ifdef X_GetImage Tk_DeleteErrorHandler(handle); #endif if (ximage == NULL) { result = TCL_OK; } else { Tcl_ResetResult(interp); result = TkPostscriptImage(interp, tkwin, Canvas(canvas)->psInfo, ximage, 0, 0, width, height); Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); XDestroyImage(ximage); } /* * Plug the accumulated postscript back into the result. */ done: if (result == TCL_OK) { (void) Tcl_RestoreInterpState(interp, interpState); Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj); } else { Tcl_DiscardInterpState(interpState); } Tcl_DecrRefCount(psObj); return result; }
static int RectOvalToPostscript( Tcl_Interp *interp, /* Interpreter for error reporting. */ Tk_Canvas canvas, /* Information about overall canvas. */ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ int prepass) /* 1 means this is a prepass to collect font * information; 0 means final Postscript is * being created. */ { Tcl_Obj *pathObj, *psObj; RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; double y1, y2; XColor *color; XColor *fillColor; Pixmap fillStipple; Tk_State state = itemPtr->state; Tcl_InterpState interpState; y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]); y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]); /* * Generate a string that creates a path for the rectangle or oval. This * is the only part of the function's code that is type-specific. */ if (rectOvalPtr->header.typePtr == &tkRectangleType) { pathObj = Tcl_ObjPrintf( "%.15g %.15g moveto " "%.15g 0 rlineto " "0 %.15g rlineto " "%.15g 0 rlineto " "closepath\n", rectOvalPtr->bbox[0], y1, rectOvalPtr->bbox[2]-rectOvalPtr->bbox[0], y2-y1, rectOvalPtr->bbox[0]-rectOvalPtr->bbox[2]); } else { pathObj = Tcl_ObjPrintf( "matrix currentmatrix\n" "%.15g %.15g translate " "%.15g %.15g scale " "1 0 moveto 0 0 1 0 360 arc\n" "setmatrix\n", (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2])/2, (y1 + y2)/2, (rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2); } if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } color = rectOvalPtr->outline.color; fillColor = rectOvalPtr->fillColor; fillStipple = rectOvalPtr->fillStipple; if (Canvas(canvas)->currentItemPtr == itemPtr) { if (rectOvalPtr->outline.activeColor!=NULL) { color = rectOvalPtr->outline.activeColor; } if (rectOvalPtr->activeFillColor!=NULL) { fillColor = rectOvalPtr->activeFillColor; } if (rectOvalPtr->activeFillStipple!=None) { fillStipple = rectOvalPtr->activeFillStipple; } } else if (state == TK_STATE_DISABLED) { if (rectOvalPtr->outline.disabledColor!=NULL) { color = rectOvalPtr->outline.disabledColor; } if (rectOvalPtr->disabledFillColor!=NULL) { fillColor = rectOvalPtr->disabledFillColor; } if (rectOvalPtr->disabledFillStipple!=None) { fillStipple = rectOvalPtr->disabledFillStipple; } } /* * Make our working space. */ psObj = Tcl_NewObj(); interpState = Tcl_SaveInterpState(interp, TCL_OK); /* * First draw the filled area of the rectangle. */ if (fillColor != NULL) { Tcl_AppendObjToObj(psObj, pathObj); Tcl_ResetResult(interp); if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) { goto error; } Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); if (fillStipple != None) { Tcl_AppendToObj(psObj, "clip ", -1); Tcl_ResetResult(interp); if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) { goto error; } Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); if (color != NULL) { Tcl_AppendToObj(psObj, "grestore gsave\n", -1); } } else { Tcl_AppendToObj(psObj, "fill\n", -1); } } /* * Now draw the outline, if there is one. */ if (color != NULL) { Tcl_AppendObjToObj(psObj, pathObj); Tcl_AppendToObj(psObj, "0 setlinejoin 2 setlinecap\n", -1); Tcl_ResetResult(interp); if (Tk_CanvasPsOutline(canvas, itemPtr, &rectOvalPtr->outline)!= TCL_OK) { goto error; } Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); } /* * Plug the accumulated postscript back into the result. */ (void) Tcl_RestoreInterpState(interp, interpState); Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj); Tcl_DecrRefCount(psObj); Tcl_DecrRefCount(pathObj); return TCL_OK; error: Tcl_DiscardInterpState(interpState); Tcl_DecrRefCount(psObj); Tcl_DecrRefCount(pathObj); return TCL_ERROR; }
static int TextToPostscript( Tcl_Interp *interp, /* Leave Postscript or error message here. */ Tk_Canvas canvas, /* Information about overall canvas. */ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ int prepass) /* 1 means this is a prepass to collect font * information; 0 means final Postscript is * being created. */ { TextItem *textPtr = (TextItem *) itemPtr; double x, y; Tk_FontMetrics fm; const char *justify; XColor *color; Pixmap stipple; Tk_State state = itemPtr->state; Tcl_Obj *psObj; Tcl_InterpState interpState; if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } color = textPtr->color; stipple = textPtr->stipple; if (state == TK_STATE_HIDDEN || textPtr->color == NULL || textPtr->text == NULL || *textPtr->text == 0) { return TCL_OK; } else if (Canvas(canvas)->currentItemPtr == itemPtr) { if (textPtr->activeColor != NULL) { color = textPtr->activeColor; } if (textPtr->activeStipple != None) { stipple = textPtr->activeStipple; } } else if (state == TK_STATE_DISABLED) { if (textPtr->disabledColor != NULL) { color = textPtr->disabledColor; } if (textPtr->disabledStipple != None) { stipple = textPtr->disabledStipple; } } /* * Make our working space. */ psObj = Tcl_NewObj(); interpState = Tcl_SaveInterpState(interp, TCL_OK); /* * Generate postscript. */ Tcl_ResetResult(interp); if (Tk_CanvasPsFont(interp, canvas, textPtr->tkfont) != TCL_OK) { goto error; } Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); if (prepass != 0) { goto done; } Tcl_ResetResult(interp); if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) { goto error; } Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); if (stipple != None) { Tcl_ResetResult(interp); Tk_CanvasPsStipple(interp, canvas, stipple); Tcl_AppendPrintfToObj(psObj, "/StippleText {\n %s} bind def\n", Tcl_GetString(Tcl_GetObjResult(interp))); } x = 0; y = 0; justify = NULL; /* lint. */ switch (textPtr->anchor) { case TK_ANCHOR_NW: x = 0; y = 0; break; case TK_ANCHOR_N: x = 1; y = 0; break; case TK_ANCHOR_NE: x = 2; y = 0; break; case TK_ANCHOR_E: x = 2; y = 1; break; case TK_ANCHOR_SE: x = 2; y = 2; break; case TK_ANCHOR_S: x = 1; y = 2; break; case TK_ANCHOR_SW: x = 0; y = 2; break; case TK_ANCHOR_W: x = 0; y = 1; break; case TK_ANCHOR_CENTER: x = 1; y = 1; break; } switch (textPtr->justify) { case TK_JUSTIFY_LEFT: justify = "0"; break; case TK_JUSTIFY_CENTER: justify = "0.5"; break; case TK_JUSTIFY_RIGHT: justify = "1"; break; } Tk_GetFontMetrics(textPtr->tkfont, &fm); Tcl_AppendPrintfToObj(psObj, "%.15g %.15g %.15g [\n", textPtr->angle, textPtr->x, Tk_CanvasPsY(canvas, textPtr->y)); Tcl_ResetResult(interp); Tk_TextLayoutToPostscript(interp, textPtr->textLayout); Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); Tcl_AppendPrintfToObj(psObj, "] %d %g %g %s %s DrawText\n", fm.linespace, x / -2.0, y / 2.0, justify, ((stipple == None) ? "false" : "true")); /* * Plug the accumulated postscript back into the result. */ done: (void) Tcl_RestoreInterpState(interp, interpState); Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj); Tcl_DecrRefCount(psObj); return TCL_OK; error: Tcl_DiscardInterpState(interpState); Tcl_DecrRefCount(psObj); return TCL_ERROR; }