tkCanvImg.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:25k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkCanvImg.c --
  3.  *
  4.  * This file implements image items for canvas widgets.
  5.  *
  6.  * Copyright (c) 1994 The Regents of the University of California.
  7.  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: tkCanvImg.c,v 1.6.2.1 2004/11/17 22:18:50 hobbs Exp $
  13.  */
  14. #include <stdio.h>
  15. #include "tkInt.h"
  16. #include "tkPort.h"
  17. #include "tkCanvas.h"
  18. /*
  19.  * The structure below defines the record for each image item.
  20.  */
  21. typedef struct ImageItem  {
  22.     Tk_Item header; /* Generic stuff that's the same for all
  23.  * types.  MUST BE FIRST IN STRUCTURE. */
  24.     Tk_Canvas canvas; /* Canvas containing the image. */
  25.     double x, y; /* Coordinates of positioning point for
  26.  * image. */
  27.     Tk_Anchor anchor; /* Where to anchor image relative to
  28.  * (x,y). */
  29.     char *imageString; /* String describing -image option (malloc-ed).
  30.  * NULL means no image right now. */
  31.     char *activeImageString; /* String describing -activeimage option.
  32.  * NULL means no image right now. */
  33.     char *disabledImageString; /* String describing -disabledimage option.
  34.  * NULL means no image right now. */
  35.     Tk_Image image; /* Image to display in window, or NULL if
  36.  * no image at present. */
  37.     Tk_Image activeImage; /* Image to display in window, or NULL if
  38.  * no image at present. */
  39.     Tk_Image disabledImage; /* Image to display in window, or NULL if
  40.  * no image at present. */
  41. } ImageItem;
  42. /*
  43.  * Information used for parsing configuration specs:
  44.  */
  45. static Tk_CustomOption stateOption = {
  46.     (Tk_OptionParseProc *) TkStateParseProc,
  47.     TkStatePrintProc, (ClientData) 2
  48. };
  49. static Tk_CustomOption tagsOption = {
  50.     (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
  51.     Tk_CanvasTagsPrintProc, (ClientData) NULL
  52. };
  53. static Tk_ConfigSpec configSpecs[] = {
  54.     {TK_CONFIG_STRING, "-activeimage", (char *) NULL, (char *) NULL,
  55. (char *) NULL, Tk_Offset(ImageItem, activeImageString),
  56. TK_CONFIG_NULL_OK},
  57.     {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
  58. "center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
  59.     {TK_CONFIG_STRING, "-disabledimage", (char *) NULL, (char *) NULL,
  60. (char *) NULL, Tk_Offset(ImageItem, disabledImageString),
  61. TK_CONFIG_NULL_OK},
  62.     {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,
  63. (char *) NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK},
  64.     {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
  65. (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
  66. &stateOption},
  67.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  68. (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
  69.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  70. (char *) NULL, 0, 0}
  71. };
  72. /*
  73.  * Prototypes for procedures defined in this file:
  74.  */
  75. static void ImageChangedProc _ANSI_ARGS_((ClientData clientData,
  76.     int x, int y, int width, int height, int imgWidth,
  77.     int imgHeight));
  78. static int ImageCoords _ANSI_ARGS_((Tcl_Interp *interp,
  79.     Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  80.     Tcl_Obj *CONST argv[]));
  81. static int ImageToArea _ANSI_ARGS_((Tk_Canvas canvas,
  82.     Tk_Item *itemPtr, double *rectPtr));
  83. static double ImageToPoint _ANSI_ARGS_((Tk_Canvas canvas,
  84.     Tk_Item *itemPtr, double *coordPtr));
  85. static int ImageToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
  86.     Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
  87. static void ComputeImageBbox _ANSI_ARGS_((Tk_Canvas canvas,
  88.     ImageItem *imgPtr));
  89. static int ConfigureImage _ANSI_ARGS_((Tcl_Interp *interp,
  90.     Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  91.     Tcl_Obj *CONST argv[], int flags));
  92. static int CreateImage _ANSI_ARGS_((Tcl_Interp *interp,
  93.     Tk_Canvas canvas, struct Tk_Item *itemPtr,
  94.     int argc, Tcl_Obj *CONST argv[]));
  95. static void DeleteImage _ANSI_ARGS_((Tk_Canvas canvas,
  96.     Tk_Item *itemPtr, Display *display));
  97. static void DisplayImage _ANSI_ARGS_((Tk_Canvas canvas,
  98.     Tk_Item *itemPtr, Display *display, Drawable dst,
  99.     int x, int y, int width, int height));
  100. static void ScaleImage _ANSI_ARGS_((Tk_Canvas canvas,
  101.     Tk_Item *itemPtr, double originX, double originY,
  102.     double scaleX, double scaleY));
  103. static void TranslateImage _ANSI_ARGS_((Tk_Canvas canvas,
  104.     Tk_Item *itemPtr, double deltaX, double deltaY));
  105. /*
  106.  * The structures below defines the image item type in terms of
  107.  * procedures that can be invoked by generic item code.
  108.  */
  109. Tk_ItemType tkImageType = {
  110.     "image", /* name */
  111.     sizeof(ImageItem), /* itemSize */
  112.     CreateImage, /* createProc */
  113.     configSpecs, /* configSpecs */
  114.     ConfigureImage, /* configureProc */
  115.     ImageCoords, /* coordProc */
  116.     DeleteImage, /* deleteProc */
  117.     DisplayImage, /* displayProc */
  118.     TK_CONFIG_OBJS, /* flags */
  119.     ImageToPoint, /* pointProc */
  120.     ImageToArea, /* areaProc */
  121.     ImageToPostscript,                 /* postscriptProc */
  122.     ScaleImage, /* scaleProc */
  123.     TranslateImage, /* translateProc */
  124.     (Tk_ItemIndexProc *) NULL, /* indexProc */
  125.     (Tk_ItemCursorProc *) NULL, /* icursorProc */
  126.     (Tk_ItemSelectionProc *) NULL, /* selectionProc */
  127.     (Tk_ItemInsertProc *) NULL, /* insertProc */
  128.     (Tk_ItemDCharsProc *) NULL, /* dTextProc */
  129.     (Tk_ItemType *) NULL, /* nextPtr */
  130. };
  131. /*
  132.  *--------------------------------------------------------------
  133.  *
  134.  * CreateImage --
  135.  *
  136.  * This procedure is invoked to create a new image
  137.  * item in a canvas.
  138.  *
  139.  * Results:
  140.  * A standard Tcl return value.  If an error occurred in
  141.  * creating the item, then an error message is left in
  142.  * the interp's result;  in this case itemPtr is left uninitialized,
  143.  * so it can be safely freed by the caller.
  144.  *
  145.  * Side effects:
  146.  * A new image item is created.
  147.  *
  148.  *--------------------------------------------------------------
  149.  */
  150. static int
  151. CreateImage(interp, canvas, itemPtr, objc, objv)
  152.     Tcl_Interp *interp; /* Interpreter for error reporting. */
  153.     Tk_Canvas canvas; /* Canvas to hold new item. */
  154.     Tk_Item *itemPtr; /* Record to hold new item;  header
  155.  * has been initialized by caller. */
  156.     int objc; /* Number of arguments in objv. */
  157.     Tcl_Obj *CONST objv[]; /* Arguments describing rectangle. */
  158. {
  159.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  160.     int i;
  161.     if (objc == 0) {
  162. panic("canvas did not pass any coordsn");
  163.     }
  164.     /*
  165.      * Initialize item's record.
  166.      */
  167.     imgPtr->canvas = canvas;
  168.     imgPtr->anchor = TK_ANCHOR_CENTER;
  169.     imgPtr->imageString = NULL;
  170.     imgPtr->activeImageString = NULL;
  171.     imgPtr->disabledImageString = NULL;
  172.     imgPtr->image = NULL;
  173.     imgPtr->activeImage = NULL;
  174.     imgPtr->disabledImage = NULL;
  175.     /*
  176.      * Process the arguments to fill in the item record.
  177.      * Only 1 (list) or 2 (x y) coords are allowed.
  178.      */
  179.     if (objc == 1) {
  180. i = 1;
  181.     } else {
  182. char *arg = Tcl_GetString(objv[1]);
  183. i = 2;
  184. if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
  185.     i = 1;
  186. }
  187.     }
  188.     if ((ImageCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {
  189. goto error;
  190.     }
  191.     if (ConfigureImage(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {
  192. return TCL_OK;
  193.     }
  194.     error:
  195.     DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
  196.     return TCL_ERROR;
  197. }
  198. /*
  199.  *--------------------------------------------------------------
  200.  *
  201.  * ImageCoords --
  202.  *
  203.  * This procedure is invoked to process the "coords" widget
  204.  * command on image items.  See the user documentation for
  205.  * details on what it does.
  206.  *
  207.  * Results:
  208.  * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
  209.  *
  210.  * Side effects:
  211.  * The coordinates for the given item may be changed.
  212.  *
  213.  *--------------------------------------------------------------
  214.  */
  215. static int
  216. ImageCoords(interp, canvas, itemPtr, objc, objv)
  217.     Tcl_Interp *interp; /* Used for error reporting. */
  218.     Tk_Canvas canvas; /* Canvas containing item. */
  219.     Tk_Item *itemPtr; /* Item whose coordinates are to be
  220.  * read or modified. */
  221.     int objc; /* Number of coordinates supplied in
  222.  * objv. */
  223.     Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1,
  224.  * x2, y2, ... */
  225. {
  226.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  227.     if (objc == 0) {
  228. Tcl_Obj *obj = Tcl_NewObj();
  229. Tcl_Obj *subobj = Tcl_NewDoubleObj(imgPtr->x);
  230. Tcl_ListObjAppendElement(interp, obj, subobj);
  231. subobj = Tcl_NewDoubleObj(imgPtr->y);
  232. Tcl_ListObjAppendElement(interp, obj, subobj);
  233. Tcl_SetObjResult(interp, obj);
  234.     } else if (objc < 3) {
  235. if (objc==1) {
  236.     if (Tcl_ListObjGetElements(interp, objv[0], &objc,
  237.     (Tcl_Obj ***) &objv) != TCL_OK) {
  238. return TCL_ERROR;
  239.     } else if (objc != 2) {
  240. char buf[64];
  241. sprintf(buf, "wrong # coordinates: expected 2, got %d", objc);
  242. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  243. return TCL_ERROR;
  244.     }
  245. }
  246. if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], &imgPtr->x) != TCL_OK)
  247. || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
  248.        &imgPtr->y) != TCL_OK)) {
  249.     return TCL_ERROR;
  250. }
  251. ComputeImageBbox(canvas, imgPtr);
  252.     } else {
  253. char buf[64];
  254. sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", objc);
  255. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  256. return TCL_ERROR;
  257.     }
  258.     return TCL_OK;
  259. }
  260. /*
  261.  *--------------------------------------------------------------
  262.  *
  263.  * ConfigureImage --
  264.  *
  265.  * This procedure is invoked to configure various aspects
  266.  * of an image item, such as its anchor position.
  267.  *
  268.  * Results:
  269.  * A standard Tcl result code.  If an error occurs, then
  270.  * an error message is left in the interp's result.
  271.  *
  272.  * Side effects:
  273.  * Configuration information may be set for itemPtr.
  274.  *
  275.  *--------------------------------------------------------------
  276.  */
  277. static int
  278. ConfigureImage(interp, canvas, itemPtr, objc, objv, flags)
  279.     Tcl_Interp *interp; /* Used for error reporting. */
  280.     Tk_Canvas canvas; /* Canvas containing itemPtr. */
  281.     Tk_Item *itemPtr; /* Image item to reconfigure. */
  282.     int objc; /* Number of elements in objv.  */
  283.     Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */
  284.     int flags; /* Flags to pass to Tk_ConfigureWidget. */
  285. {
  286.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  287.     Tk_Window tkwin;
  288.     Tk_Image image;
  289.     tkwin = Tk_CanvasTkwin(canvas);
  290.     if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
  291.     (CONST char **) objv, (char *) imgPtr, flags|TK_CONFIG_OBJS)) {
  292. return TCL_ERROR;
  293.     }
  294.     /*
  295.      * Create the image.  Save the old image around and don't free it
  296.      * until after the new one is allocated.  This keeps the reference
  297.      * count from going to zero so the image doesn't have to be recreated
  298.      * if it hasn't changed.
  299.      */
  300.     if (imgPtr->activeImageString != NULL) {
  301. itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
  302.     } else {
  303. itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
  304.     }
  305.     if (imgPtr->imageString != NULL) {
  306. image = Tk_GetImage(interp, tkwin, imgPtr->imageString,
  307. ImageChangedProc, (ClientData) imgPtr);
  308. if (image == NULL) {
  309.     return TCL_ERROR;
  310. }
  311.     } else {
  312. image = NULL;
  313.     }
  314.     if (imgPtr->image != NULL) {
  315. Tk_FreeImage(imgPtr->image);
  316.     }
  317.     imgPtr->image = image;
  318.     if (imgPtr->activeImageString != NULL) {
  319. image = Tk_GetImage(interp, tkwin, imgPtr->activeImageString,
  320. ImageChangedProc, (ClientData) imgPtr);
  321. if (image == NULL) {
  322.     return TCL_ERROR;
  323. }
  324.     } else {
  325. image = NULL;
  326.     }
  327.     if (imgPtr->activeImage != NULL) {
  328. Tk_FreeImage(imgPtr->activeImage);
  329.     }
  330.     imgPtr->activeImage = image;
  331.     if (imgPtr->disabledImageString != NULL) {
  332. image = Tk_GetImage(interp, tkwin, imgPtr->disabledImageString,
  333. ImageChangedProc, (ClientData) imgPtr);
  334. if (image == NULL) {
  335.     return TCL_ERROR;
  336. }
  337.     } else {
  338. image = NULL;
  339.     }
  340.     if (imgPtr->disabledImage != NULL) {
  341. Tk_FreeImage(imgPtr->disabledImage);
  342.     }
  343.     imgPtr->disabledImage = image;
  344.     ComputeImageBbox(canvas, imgPtr);
  345.     return TCL_OK;
  346. }
  347. /*
  348.  *--------------------------------------------------------------
  349.  *
  350.  * DeleteImage --
  351.  *
  352.  * This procedure is called to clean up the data structure
  353.  * associated with a image item.
  354.  *
  355.  * Results:
  356.  * None.
  357.  *
  358.  * Side effects:
  359.  * Resources associated with itemPtr are released.
  360.  *
  361.  *--------------------------------------------------------------
  362.  */
  363. static void
  364. DeleteImage(canvas, itemPtr, display)
  365.     Tk_Canvas canvas; /* Info about overall canvas widget. */
  366.     Tk_Item *itemPtr; /* Item that is being deleted. */
  367.     Display *display; /* Display containing window for
  368.  * canvas. */
  369. {
  370.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  371.     if (imgPtr->imageString != NULL) {
  372. ckfree(imgPtr->imageString);
  373.     }
  374.     if (imgPtr->activeImageString != NULL) {
  375. ckfree(imgPtr->activeImageString);
  376.     }
  377.     if (imgPtr->disabledImageString != NULL) {
  378. ckfree(imgPtr->disabledImageString);
  379.     }
  380.     if (imgPtr->image != NULL) {
  381. Tk_FreeImage(imgPtr->image);
  382.     }
  383.     if (imgPtr->activeImage != NULL) {
  384. Tk_FreeImage(imgPtr->activeImage);
  385.     }
  386.     if (imgPtr->disabledImage != NULL) {
  387. Tk_FreeImage(imgPtr->disabledImage);
  388.     }
  389. }
  390. /*
  391.  *--------------------------------------------------------------
  392.  *
  393.  * ComputeImageBbox --
  394.  *
  395.  * This procedure is invoked to compute the bounding box of
  396.  * all the pixels that may be drawn as part of a image item.
  397.  * This procedure is where the child image's placement is
  398.  * computed.
  399.  *
  400.  * Results:
  401.  * None.
  402.  *
  403.  * Side effects:
  404.  * The fields x1, y1, x2, and y2 are updated in the header
  405.  * for itemPtr.
  406.  *
  407.  *--------------------------------------------------------------
  408.  */
  409. /* ARGSUSED */
  410. static void
  411. ComputeImageBbox(canvas, imgPtr)
  412.     Tk_Canvas canvas; /* Canvas that contains item. */
  413.     ImageItem *imgPtr; /* Item whose bbox is to be
  414.  * recomputed. */
  415. {
  416.     int width, height;
  417.     int x, y;
  418.     Tk_Image image;
  419.     Tk_State state = imgPtr->header.state;
  420.     if(state == TK_STATE_NULL) {
  421. state = ((TkCanvas *)canvas)->canvas_state;
  422.     }
  423.     image = imgPtr->image;
  424.     if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)imgPtr) {
  425. if (imgPtr->activeImage != NULL) {
  426.     image = imgPtr->activeImage;
  427. }
  428.     } else if (state == TK_STATE_DISABLED) {
  429. if (imgPtr->disabledImage != NULL) {
  430.     image = imgPtr->disabledImage;
  431. }
  432.     }
  433.     x = (int) (imgPtr->x + ((imgPtr->x >= 0) ? 0.5 : - 0.5));
  434.     y = (int) (imgPtr->y + ((imgPtr->y >= 0) ? 0.5 : - 0.5));
  435.     if ((state == TK_STATE_HIDDEN) || (image == None)) {
  436. imgPtr->header.x1 = imgPtr->header.x2 = x;
  437. imgPtr->header.y1 = imgPtr->header.y2 = y;
  438. return;
  439.     }
  440.     /*
  441.      * Compute location and size of image, using anchor information.
  442.      */
  443.     Tk_SizeOfImage(image, &width, &height);
  444.     switch (imgPtr->anchor) {
  445. case TK_ANCHOR_N:
  446.     x -= width/2;
  447.     break;
  448. case TK_ANCHOR_NE:
  449.     x -= width;
  450.     break;
  451. case TK_ANCHOR_E:
  452.     x -= width;
  453.     y -= height/2;
  454.     break;
  455. case TK_ANCHOR_SE:
  456.     x -= width;
  457.     y -= height;
  458.     break;
  459. case TK_ANCHOR_S:
  460.     x -= width/2;
  461.     y -= height;
  462.     break;
  463. case TK_ANCHOR_SW:
  464.     y -= height;
  465.     break;
  466. case TK_ANCHOR_W:
  467.     y -= height/2;
  468.     break;
  469. case TK_ANCHOR_NW:
  470.     break;
  471. case TK_ANCHOR_CENTER:
  472.     x -= width/2;
  473.     y -= height/2;
  474.     break;
  475.     }
  476.     /*
  477.      * Store the information in the item header.
  478.      */
  479.     imgPtr->header.x1 = x;
  480.     imgPtr->header.y1 = y;
  481.     imgPtr->header.x2 = x + width;
  482.     imgPtr->header.y2 = y + height;
  483. }
  484. /*
  485.  *--------------------------------------------------------------
  486.  *
  487.  * DisplayImage --
  488.  *
  489.  * This procedure is invoked to draw a image item in a given
  490.  * drawable.
  491.  *
  492.  * Results:
  493.  * None.
  494.  *
  495.  * Side effects:
  496.  * ItemPtr is drawn in drawable using the transformation
  497.  * information in canvas.
  498.  *
  499.  *--------------------------------------------------------------
  500.  */
  501. static void
  502. DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height)
  503.     Tk_Canvas canvas; /* Canvas that contains item. */
  504.     Tk_Item *itemPtr; /* Item to be displayed. */
  505.     Display *display; /* Display on which to draw item. */
  506.     Drawable drawable; /* Pixmap or window in which to draw
  507.  * item. */
  508.     int x, y, width, height; /* Describes region of canvas that
  509.  * must be redisplayed (not used). */
  510. {
  511.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  512.     short drawableX, drawableY;
  513.     Tk_Image image;
  514.     Tk_State state = itemPtr->state;
  515.     if(state == TK_STATE_NULL) {
  516. state = ((TkCanvas *)canvas)->canvas_state;
  517.     }
  518.     image = imgPtr->image;
  519.     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
  520. if (imgPtr->activeImage != NULL) {
  521.     image = imgPtr->activeImage;
  522. }
  523.     } else if (state == TK_STATE_DISABLED) {
  524. if (imgPtr->disabledImage != NULL) {
  525.     image = imgPtr->disabledImage;
  526. }
  527.     }
  528.     if (image == NULL) {
  529. return;
  530.     }
  531.     /*
  532.      * Translate the coordinates to those of the image, then redisplay it.
  533.      */
  534.     Tk_CanvasDrawableCoords(canvas, (double) x, (double) y,
  535.     &drawableX, &drawableY);
  536.     Tk_RedrawImage(image, x - imgPtr->header.x1, y - imgPtr->header.y1,
  537.     width, height, drawable, drawableX, drawableY);
  538. }
  539. /*
  540.  *--------------------------------------------------------------
  541.  *
  542.  * ImageToPoint --
  543.  *
  544.  * Computes the distance from a given point to a given
  545.  * rectangle, in canvas units.
  546.  *
  547.  * Results:
  548.  * The return value is 0 if the point whose x and y coordinates
  549.  * are coordPtr[0] and coordPtr[1] is inside the image.  If the
  550.  * point isn't inside the image then the return value is the
  551.  * distance from the point to the image.
  552.  *
  553.  * Side effects:
  554.  * None.
  555.  *
  556.  *--------------------------------------------------------------
  557.  */
  558. static double
  559. ImageToPoint(canvas, itemPtr, coordPtr)
  560.     Tk_Canvas canvas; /* Canvas containing item. */
  561.     Tk_Item *itemPtr; /* Item to check against point. */
  562.     double *coordPtr; /* Pointer to x and y coordinates. */
  563. {
  564.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  565.     double x1, x2, y1, y2, xDiff, yDiff;
  566.     x1 = imgPtr->header.x1;
  567.     y1 = imgPtr->header.y1;
  568.     x2 = imgPtr->header.x2;
  569.     y2 = imgPtr->header.y2;
  570.     /*
  571.      * Point is outside rectangle.
  572.      */
  573.     if (coordPtr[0] < x1) {
  574. xDiff = x1 - coordPtr[0];
  575.     } else if (coordPtr[0] > x2)  {
  576. xDiff = coordPtr[0] - x2;
  577.     } else {
  578. xDiff = 0;
  579.     }
  580.     if (coordPtr[1] < y1) {
  581. yDiff = y1 - coordPtr[1];
  582.     } else if (coordPtr[1] > y2)  {
  583. yDiff = coordPtr[1] - y2;
  584.     } else {
  585. yDiff = 0;
  586.     }
  587.     return hypot(xDiff, yDiff);
  588. }
  589. /*
  590.  *--------------------------------------------------------------
  591.  *
  592.  * ImageToArea --
  593.  *
  594.  * This procedure is called to determine whether an item
  595.  * lies entirely inside, entirely outside, or overlapping
  596.  * a given rectangle.
  597.  *
  598.  * Results:
  599.  * -1 is returned if the item is entirely outside the area
  600.  * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  601.  * inside the given area.
  602.  *
  603.  * Side effects:
  604.  * None.
  605.  *
  606.  *--------------------------------------------------------------
  607.  */
  608. static int
  609. ImageToArea(canvas, itemPtr, rectPtr)
  610.     Tk_Canvas canvas; /* Canvas containing item. */
  611.     Tk_Item *itemPtr; /* Item to check against rectangle. */
  612.     double *rectPtr; /* Pointer to array of four coordinates
  613.  * (x1, y1, x2, y2) describing rectangular
  614.  * area.  */
  615. {
  616.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  617.     if ((rectPtr[2] <= imgPtr->header.x1)
  618.     || (rectPtr[0] >= imgPtr->header.x2)
  619.     || (rectPtr[3] <= imgPtr->header.y1)
  620.     || (rectPtr[1] >= imgPtr->header.y2)) {
  621. return -1;
  622.     }
  623.     if ((rectPtr[0] <= imgPtr->header.x1)
  624.     && (rectPtr[1] <= imgPtr->header.y1)
  625.     && (rectPtr[2] >= imgPtr->header.x2)
  626.     && (rectPtr[3] >= imgPtr->header.y2)) {
  627. return 1;
  628.     }
  629.     return 0;
  630. }
  631. /*
  632.  *--------------------------------------------------------------
  633.  *
  634.  * ImageToPostscript --
  635.  *
  636.  * This procedure is called to generate Postscript for
  637.  * image items.
  638.  *
  639.  * Results:
  640.  * The return value is a standard Tcl result.  If an error
  641.  * occurs in generating Postscript then an error message is
  642.  * left in interp->result, replacing whatever used to be there.
  643.  * If no error occurs, then Postscript for the item is appended
  644.  * to the result.
  645.  *
  646.  * Side effects:
  647.  * None.
  648.  *
  649.  *--------------------------------------------------------------
  650.  */
  651. static int
  652. ImageToPostscript(interp, canvas, itemPtr, prepass)
  653.     Tcl_Interp *interp; /* Leave Postscript or error message
  654.  * here. */
  655.     Tk_Canvas canvas; /* Information about overall canvas. */
  656.     Tk_Item *itemPtr; /* Item for which Postscript is
  657.  * wanted. */
  658.     int prepass; /* 1 means this is a prepass to
  659.  * collect font information;  0 means
  660.  * final Postscript is being created.*/
  661. {
  662.     ImageItem *imgPtr = (ImageItem *)itemPtr;
  663.     Tk_Window canvasWin = Tk_CanvasTkwin(canvas);
  664.     char buffer[256];
  665.     double x, y;
  666.     int width, height;
  667.     Tk_Image image;
  668.     Tk_State state = itemPtr->state;
  669.     if (state == TK_STATE_NULL) {
  670. state = ((TkCanvas *)canvas)->canvas_state;
  671.     }
  672.     image = imgPtr->image;
  673.     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
  674. if (imgPtr->activeImage != NULL) {
  675.     image = imgPtr->activeImage;
  676. }
  677.     } else if (state == TK_STATE_DISABLED) {
  678. if (imgPtr->disabledImage != NULL) {
  679.     image = imgPtr->disabledImage;
  680. }
  681.     }
  682.     if (image == NULL) {
  683. /*
  684.  * Image item without actual image specified.
  685.  */
  686. return TCL_OK;
  687.     }
  688.     Tk_SizeOfImage(image, &width, &height);
  689.     /*
  690.      * Compute the coordinates of the lower-left corner of the image,
  691.      * taking into account the anchor position for the image.
  692.      */
  693.     x = imgPtr->x;
  694.     y = Tk_CanvasPsY(canvas, imgPtr->y);
  695.     switch (imgPtr->anchor) {
  696. case TK_ANCHOR_NW: y -= height; break;
  697. case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
  698. case TK_ANCHOR_NE: x -= width; y -= height; break;
  699. case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
  700. case TK_ANCHOR_SE: x -= width; break;
  701. case TK_ANCHOR_S: x -= width/2.0; break;
  702. case TK_ANCHOR_SW: break;
  703. case TK_ANCHOR_W: y -= height/2.0; break;
  704. case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
  705.     }
  706.     if (!prepass) {
  707. sprintf(buffer, "%.15g %.15g", x, y);
  708. Tcl_AppendResult(interp, buffer, " translaten", (char *) NULL);
  709.     }
  710.     return Tk_PostscriptImage(image, interp, canvasWin,
  711.     ((TkCanvas *) canvas)->psInfo, 0, 0, width, height, prepass);
  712. }
  713. /*
  714.  *--------------------------------------------------------------
  715.  *
  716.  * ScaleImage --
  717.  *
  718.  * This procedure is invoked to rescale an item.
  719.  *
  720.  * Results:
  721.  * None.
  722.  *
  723.  * Side effects:
  724.  * The item referred to by itemPtr is rescaled so that the
  725.  * following transformation is applied to all point coordinates:
  726.  * x' = originX + scaleX*(x-originX)
  727.  * y' = originY + scaleY*(y-originY)
  728.  *
  729.  *--------------------------------------------------------------
  730.  */
  731. static void
  732. ScaleImage(canvas, itemPtr, originX, originY, scaleX, scaleY)
  733.     Tk_Canvas canvas; /* Canvas containing rectangle. */
  734.     Tk_Item *itemPtr; /* Rectangle to be scaled. */
  735.     double originX, originY; /* Origin about which to scale rect. */
  736.     double scaleX; /* Amount to scale in X direction. */
  737.     double scaleY; /* Amount to scale in Y direction. */
  738. {
  739.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  740.     imgPtr->x = originX + scaleX*(imgPtr->x - originX);
  741.     imgPtr->y = originY + scaleY*(imgPtr->y - originY);
  742.     ComputeImageBbox(canvas, imgPtr);
  743. }
  744. /*
  745.  *--------------------------------------------------------------
  746.  *
  747.  * TranslateImage --
  748.  *
  749.  * This procedure is called to move an item by a given amount.
  750.  *
  751.  * Results:
  752.  * None.
  753.  *
  754.  * Side effects:
  755.  * The position of the item is offset by (xDelta, yDelta), and
  756.  * the bounding box is updated in the generic part of the item
  757.  * structure.
  758.  *
  759.  *--------------------------------------------------------------
  760.  */
  761. static void
  762. TranslateImage(canvas, itemPtr, deltaX, deltaY)
  763.     Tk_Canvas canvas; /* Canvas containing item. */
  764.     Tk_Item *itemPtr; /* Item that is being moved. */
  765.     double deltaX, deltaY; /* Amount by which item is to be
  766.  * moved. */
  767. {
  768.     ImageItem *imgPtr = (ImageItem *) itemPtr;
  769.     imgPtr->x += deltaX;
  770.     imgPtr->y += deltaY;
  771.     ComputeImageBbox(canvas, imgPtr);
  772. }
  773. /*
  774.  *----------------------------------------------------------------------
  775.  *
  776.  * ImageChangedProc --
  777.  *
  778.  * This procedure is invoked by the image code whenever the manager
  779.  * for an image does something that affects the image's size or
  780.  * how it is displayed.
  781.  *
  782.  * Results:
  783.  * None.
  784.  *
  785.  * Side effects:
  786.  * Arranges for the canvas to get redisplayed.
  787.  *
  788.  *----------------------------------------------------------------------
  789.  */
  790. static void
  791. ImageChangedProc(clientData, x, y, width, height, imgWidth, imgHeight)
  792.     ClientData clientData; /* Pointer to canvas item for image. */
  793.     int x, y; /* Upper left pixel (within image)
  794.  * that must be redisplayed. */
  795.     int width, height; /* Dimensions of area to redisplay
  796.  * (may be <= 0). */
  797.     int imgWidth, imgHeight; /* New dimensions of image. */
  798. {
  799.     ImageItem *imgPtr = (ImageItem *) clientData;
  800.     /*
  801.      * If the image's size changed and it's not anchored at its
  802.      * northwest corner then just redisplay the entire area of the
  803.      * image.  This is a bit over-conservative, but we need to do
  804.      * something because a size change also means a position change.
  805.      */
  806.     if (((imgPtr->header.x2 - imgPtr->header.x1) != imgWidth)
  807.     || ((imgPtr->header.y2 - imgPtr->header.y1) != imgHeight)) {
  808. x = y = 0;
  809. width = imgWidth;
  810. height = imgHeight;
  811. Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1,
  812. imgPtr->header.y1, imgPtr->header.x2, imgPtr->header.y2);
  813.     } 
  814.     ComputeImageBbox(imgPtr->canvas, imgPtr);
  815.     Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1 + x,
  816.     imgPtr->header.y1 + y, (int) (imgPtr->header.x1 + x + width),
  817.     (int) (imgPtr->header.y1 + y + height));
  818. }