/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkcanvimg.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkcanvimg.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.29  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25