/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkimage.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkimage.c

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

revision 44 by dashley, Fri Oct 14 02:09:58 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkimage.c,v 1.1.1.1 2001/06/13 05:02:12 dtashley Exp $ */  
   
 /*  
  * tkImage.c --  
  *  
  *      This module implements the image protocol, which allows lots  
  *      of different kinds of images to be used in lots of different  
  *      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: tkimage.c,v 1.1.1.1 2001/06/13 05:02:12 dtashley Exp $  
  */  
   
 #include "tkInt.h"  
 #include "tkPort.h"  
   
 /*  
  * Each call to Tk_GetImage returns a pointer to one of the following  
  * structures, which is used as a token by clients (widgets) that  
  * display images.  
  */  
   
 typedef struct Image {  
     Tk_Window tkwin;            /* Window passed to Tk_GetImage (needed to  
                                  * "re-get" the image later if the manager  
                                  * changes). */  
     Display *display;           /* Display for tkwin.  Needed because when  
                                  * the image is eventually freed tkwin may  
                                  * not exist anymore. */  
     struct ImageMaster *masterPtr;  
                                 /* Master for this image (identifiers image  
                                  * manager, for example). */  
     ClientData instanceData;  
                                 /* One word argument to pass to image manager  
                                  * when dealing with this image instance. */  
     Tk_ImageChangedProc *changeProc;  
                                 /* Code in widget to call when image changes  
                                  * in a way that affects redisplay. */  
     ClientData widgetClientData;  
                                 /* Argument to pass to changeProc. */  
     struct Image *nextPtr;      /* Next in list of all image instances  
                                  * associated with the same name. */  
   
 } Image;  
   
 /*  
  * For each image master there is one of the following structures,  
  * which represents a name in the image table and all of the images  
  * instantiated from it.  Entries in mainPtr->imageTable point to  
  * these structures.  
  */  
   
 typedef struct ImageMaster {  
     Tk_ImageType *typePtr;      /* Information about image type.  NULL means  
                                  * that no image manager owns this image:  the  
                                  * image was deleted. */  
     ClientData masterData;      /* One-word argument to pass to image mgr  
                                  * when dealing with the master, as opposed  
                                  * to instances. */  
     int width, height;          /* Last known dimensions for image. */  
     Tcl_HashTable *tablePtr;    /* Pointer to hash table containing image  
                                  * (the imageTable field in some TkMainInfo  
                                  * structure). */  
     Tcl_HashEntry *hPtr;        /* Hash entry in mainPtr->imageTable for  
                                  * this structure (used to delete the hash  
                                  * entry). */  
     Image *instancePtr;         /* Pointer to first in list of instances  
                                  * derived from this name. */  
 } ImageMaster;  
   
 typedef struct ThreadSpecificData {  
     Tk_ImageType *imageTypeList;/* First in a list of all known image  
                                  * types. */    
     Tk_ImageType *oldImageTypeList;/* First in a list of all known old-style image  
                                  * types. */    
 } ThreadSpecificData;            
 static Tcl_ThreadDataKey dataKey;  
   
 /*  
  * Prototypes for local procedures:  
  */  
   
 static void             DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_CreateOldImageType, Tk_CreateImageType --  
  *  
  *      This procedure is invoked by an image manager to tell Tk about  
  *      a new kind of image and the procedures that manage the new type.  
  *      The procedure is typically invoked during Tcl_AppInit.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The new image type is entered into a table used in the "image  
  *      create" command.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 Tk_CreateOldImageType(typePtr)  
     Tk_ImageType *typePtr;      /* Structure describing the type.  All of  
                                  * the fields except "nextPtr" must be filled  
                                  * in by caller.  Must not have been passed  
                                  * to Tk_CreateImageType previously. */  
 {  
     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)  
             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));  
   
     typePtr->nextPtr = tsdPtr->oldImageTypeList;  
     tsdPtr->oldImageTypeList = typePtr;  
 }  
   
 void  
 Tk_CreateImageType(typePtr)  
     Tk_ImageType *typePtr;      /* Structure describing the type.  All of  
                                  * the fields except "nextPtr" must be filled  
                                  * in by caller.  Must not have been passed  
                                  * to Tk_CreateImageType previously. */  
 {  
     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)  
             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));  
   
     typePtr->nextPtr = tsdPtr->imageTypeList;  
     tsdPtr->imageTypeList = typePtr;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_ImageObjCmd --  
  *  
  *      This procedure is invoked to process the "image" Tcl command.  
  *      See the user documentation for details on what it does.  
  *  
  * Results:  
  *      A standard Tcl result.  
  *  
  * Side effects:  
  *      See the user documentation.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 Tk_ImageObjCmd(clientData, interp, objc, objv)  
     ClientData clientData;      /* Main window associated with interpreter. */  
     Tcl_Interp *interp;         /* Current interpreter. */  
     int objc;                   /* Number of arguments. */  
     Tcl_Obj *CONST objv[];      /* Argument strings. */  
 {  
     static char *imageOptions[] = {  
         "create", "delete", "height", "names", "type", "types", "width",  
         (char *) NULL  
     };  
     enum options {  
         IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_NAMES,  
         IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH  
     };  
     TkWindow *winPtr = (TkWindow *) clientData;  
     int i, new, firstOption,  index;  
     Tk_ImageType *typePtr;  
     ImageMaster *masterPtr;  
     Image *imagePtr;  
     Tcl_HashEntry *hPtr;  
     Tcl_HashSearch search;  
     char idString[16 + TCL_INTEGER_SPACE], *name;  
     TkDisplay *dispPtr = winPtr->dispPtr;  
     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)  
             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));  
   
     if (objc < 2) {  
         Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");  
         return TCL_ERROR;  
     }  
   
     if (Tcl_GetIndexFromObj(interp, objv[1], imageOptions, "option", 0,  
             &index) != TCL_OK) {  
         return TCL_ERROR;  
     }  
     switch ((enum options) index) {  
         case IMAGE_CREATE: {  
             char *arg;  
             Tcl_Obj **args;  
             int oldimage = 0;  
             if (objc < 3) {  
                 Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?");  
                 return TCL_ERROR;  
             }  
   
             /*  
              * Look up the image type.  
              */  
   
             arg = Tcl_GetString(objv[2]);  
             for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;  
                  typePtr = typePtr->nextPtr) {  
                 if ((*arg == typePtr->name[0])  
                         && (strcmp(arg, typePtr->name) == 0)) {  
                     break;  
                 }  
             }  
             if (typePtr == NULL) {  
                 oldimage = 1;  
                 for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;  
                      typePtr = typePtr->nextPtr) {  
                     if ((*arg == typePtr->name[0])  
                             && (strcmp(arg, typePtr->name) == 0)) {  
                         break;  
                     }  
                 }  
             }  
             if (typePtr == NULL) {  
                 Tcl_AppendResult(interp, "image type \"", arg,  
                         "\" doesn't exist", (char *) NULL);  
                 return TCL_ERROR;  
             }  
   
             /*  
              * Figure out a name to use for the new image.  
              */  
   
             if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) {  
                 dispPtr->imageId++;  
                 sprintf(idString, "image%d", dispPtr->imageId);  
                 name = idString;  
                 firstOption = 3;  
             } else {  
                 name = arg;  
                 firstOption = 4;  
             }  
   
             /*  
              * Create the data structure for the new image.  
              */  
   
             hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable,  
                     name, &new);  
             if (new) {  
                 masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster));  
                 masterPtr->typePtr = NULL;  
                 masterPtr->masterData = NULL;  
                 masterPtr->width = masterPtr->height = 1;  
                 masterPtr->tablePtr = &winPtr->mainPtr->imageTable;  
                 masterPtr->hPtr = hPtr;  
                 masterPtr->instancePtr = NULL;  
                 Tcl_SetHashValue(hPtr, masterPtr);  
             } else {  
                 /*  
                  * An image already exists by this name.  Disconnect the  
                  * instances from the master.  
                  */  
   
                 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);  
                 if (masterPtr->typePtr != NULL) {  
                     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;  
                          imagePtr = imagePtr->nextPtr) {  
                         (*masterPtr->typePtr->freeProc)(  
                             imagePtr->instanceData, imagePtr->display);  
                         (*imagePtr->changeProc)(imagePtr->widgetClientData,  
                                 0, 0, masterPtr->width, masterPtr->height,  
                                 masterPtr->width, masterPtr->height);  
                     }  
                     (*masterPtr->typePtr->deleteProc)(masterPtr->masterData);  
                     masterPtr->typePtr = NULL;  
                 }  
             }  
   
             /*  
              * Call the image type manager so that it can perform its own  
              * initialization, then re-"get" for any existing instances of  
              * the image.  
              */  
   
             objv += firstOption;  
             objc -= firstOption;  
             args = (Tcl_Obj **) objv;  
             if (oldimage) {  
                 int i;  
                 args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *));  
                 for (i = 0; i < objc; i++) {  
                     args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]);  
                 }  
                 args[objc] = NULL;  
             }  
             if ((*typePtr->createProc)(interp, name, objc,  
                     args, typePtr, (Tk_ImageMaster) masterPtr,  
                     &masterPtr->masterData) != TCL_OK) {  
                 DeleteImage(masterPtr);  
                 if (oldimage) {  
                     ckfree((char *) args);  
                 }  
                 return TCL_ERROR;  
             }  
             if (oldimage) {  
                 ckfree((char *) args);  
             }  
             masterPtr->typePtr = typePtr;  
             for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;  
                  imagePtr = imagePtr->nextPtr) {  
                 imagePtr->instanceData = (*typePtr->getProc)(  
                     imagePtr->tkwin, masterPtr->masterData);  
             }  
             Tcl_SetResult(interp,  
                     Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr),  
                     TCL_STATIC);  
             break;  
         }  
         case IMAGE_DELETE: {  
             for (i = 2; i < objc; i++) {  
                 char *arg = Tcl_GetString(objv[i]);  
                 hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);  
                 if (hPtr == NULL) {  
                     Tcl_AppendResult(interp, "image \"", arg,  
                             "\" doesn't exist", (char *) NULL);  
                     return TCL_ERROR;  
                 }  
                 masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);  
                 DeleteImage(masterPtr);  
             }  
             break;  
         }  
         case IMAGE_HEIGHT: {      
             char *arg;  
             if (objc != 3) {  
                 Tcl_WrongNumArgs(interp, 2, objv, "name");  
                 return TCL_ERROR;  
             }  
             arg = Tcl_GetString(objv[2]);  
             hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);  
             if (hPtr == NULL) {  
                 Tcl_AppendResult(interp, "image \"", arg,  
                         "\" doesn't exist", (char *) NULL);  
                 return TCL_ERROR;  
             }  
             masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);  
             Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height);  
             break;  
         }  
         case IMAGE_NAMES: {  
             if (objc != 2) {  
                 Tcl_WrongNumArgs(interp, 2, objv, NULL);  
                 return TCL_ERROR;  
             }  
             for (hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);  
                  hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {  
                 Tcl_AppendElement(interp, Tcl_GetHashKey(  
                     &winPtr->mainPtr->imageTable, hPtr));  
             }  
             break;  
         }  
         case IMAGE_TYPE: {  
             char *arg;  
             if (objc != 3) {  
                 Tcl_WrongNumArgs(interp, 2, objv, "name");  
                 return TCL_ERROR;  
             }  
             arg = Tcl_GetString(objv[2]);  
             hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);  
             if (hPtr == NULL) {  
                 Tcl_AppendResult(interp, "image \"", arg,  
                         "\" doesn't exist", (char *) NULL);  
                 return TCL_ERROR;  
             }  
             masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);  
             if (masterPtr->typePtr != NULL) {  
                 Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC);  
             }  
             break;  
         }  
         case IMAGE_TYPES: {  
             if (objc != 2) {  
                 Tcl_WrongNumArgs(interp, 2, objv, NULL);  
                 return TCL_ERROR;  
             }  
             for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;  
                  typePtr = typePtr->nextPtr) {  
                 Tcl_AppendElement(interp, typePtr->name);  
             }  
             for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;  
                  typePtr = typePtr->nextPtr) {  
                 Tcl_AppendElement(interp, typePtr->name);  
             }  
             break;  
         }  
         case IMAGE_WIDTH: {  
             char *arg;  
             if (objc != 3) {  
                 Tcl_WrongNumArgs(interp, 2, objv, "name");  
                 return TCL_ERROR;  
             }  
             arg = Tcl_GetString(objv[2]);  
             hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);  
             if (hPtr == NULL) {  
                 Tcl_AppendResult(interp, "image \"", arg,  
                         "\" doesn't exist", (char *) NULL);  
                 return TCL_ERROR;  
             }  
             masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);  
             Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width);  
             break;  
         }  
     }  
     return TCL_OK;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_ImageChanged --  
  *  
  *      This procedure is called by an image manager whenever something  
  *      has happened that requires the image to be redrawn (some of its  
  *      pixels have changed, or its size has changed).  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Any widgets that display the image are notified so that they  
  *      can redisplay themselves as appropriate.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth,  
         imageHeight)  
     Tk_ImageMaster imageMaster; /* Image that needs redisplay. */  
     int x, y;                   /* Coordinates of upper-left pixel of  
                                  * region of image that needs to be  
                                  * redrawn. */  
     int width, height;          /* Dimensions (in pixels) of region of  
                                  * image to redraw.  If either dimension  
                                  * is zero then the image doesn't need to  
                                  * be redrawn (perhaps all that happened is  
                                  * that its size changed). */  
     int imageWidth, imageHeight;/* New dimensions of image. */  
 {  
     ImageMaster *masterPtr = (ImageMaster *) imageMaster;  
     Image *imagePtr;  
   
     masterPtr->width = imageWidth;  
     masterPtr->height = imageHeight;  
     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;  
          imagePtr = imagePtr->nextPtr) {  
         (*imagePtr->changeProc)(imagePtr->widgetClientData, x, y,  
                 width, height, imageWidth, imageHeight);  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_NameOfImage --  
  *  
  *      Given a token for an image master, this procedure returns  
  *      the name of the image.  
  *  
  * Results:  
  *      The return value is the string name for imageMaster.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 char *  
 Tk_NameOfImage(imageMaster)  
     Tk_ImageMaster imageMaster;         /* Token for image. */  
 {  
     ImageMaster *masterPtr = (ImageMaster *) imageMaster;  
   
     return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_GetImage --  
  *  
  *      This procedure is invoked by a widget when it wants to use  
  *      a particular image in a particular window.  
  *  
  * Results:  
  *      The return value is a token for the image.  If there is no image  
  *      by the given name, then NULL is returned and an error message is  
  *      left in the interp's result.  
  *  
  * Side effects:  
  *      Tk records the fact that the widget is using the image, and  
  *      it will invoke changeProc later if the widget needs redisplay  
  *      (i.e. its size changes or some of its pixels change).  The  
  *      caller must eventually invoke Tk_FreeImage when it no longer  
  *      needs the image.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 Tk_Image  
 Tk_GetImage(interp, tkwin, name, changeProc, clientData)  
     Tcl_Interp *interp;         /* Place to leave error message if image  
                                  * can't be found. */  
     Tk_Window tkwin;            /* Token for window in which image will  
                                  * be used. */  
     char *name;                 /* Name of desired image. */  
     Tk_ImageChangedProc *changeProc;  
                                 /* Procedure to invoke when redisplay is  
                                  * needed because image's pixels or size  
                                  * changed. */  
     ClientData clientData;      /* One-word argument to pass to damageProc. */  
 {  
     Tcl_HashEntry *hPtr;  
     ImageMaster *masterPtr;  
     Image *imagePtr;  
   
     hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);  
     if (hPtr == NULL) {  
         goto noSuchImage;  
     }  
     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);  
     if (masterPtr->typePtr == NULL) {  
         goto noSuchImage;  
     }  
     imagePtr = (Image *) ckalloc(sizeof(Image));  
     imagePtr->tkwin = tkwin;  
     imagePtr->display = Tk_Display(tkwin);  
     imagePtr->masterPtr = masterPtr;  
     imagePtr->instanceData =  
             (*masterPtr->typePtr->getProc)(tkwin, masterPtr->masterData);  
     imagePtr->changeProc = changeProc;  
     imagePtr->widgetClientData = clientData;  
     imagePtr->nextPtr = masterPtr->instancePtr;  
     masterPtr->instancePtr = imagePtr;  
     return (Tk_Image) imagePtr;  
   
     noSuchImage:  
     Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist",  
             (char *) NULL);  
     return NULL;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_FreeImage --  
  *  
  *      This procedure is invoked by a widget when it no longer needs  
  *      an image acquired by a previous call to Tk_GetImage.  For each  
  *      call to Tk_GetImage there must be exactly one call to Tk_FreeImage.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The association between the image and the widget is removed.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 Tk_FreeImage(image)  
     Tk_Image image;             /* Token for image that is no longer  
                                  * needed by a widget. */  
 {  
     Image *imagePtr = (Image *) image;  
     ImageMaster *masterPtr = imagePtr->masterPtr;  
     Image *prevPtr;  
   
     /*  
      * Clean up the particular instance.  
      */  
   
     if (masterPtr->typePtr != NULL) {  
         (*masterPtr->typePtr->freeProc)(imagePtr->instanceData,  
                 imagePtr->display);  
     }  
     prevPtr = masterPtr->instancePtr;  
     if (prevPtr == imagePtr) {  
         masterPtr->instancePtr = imagePtr->nextPtr;  
     } else {  
         while (prevPtr->nextPtr != imagePtr) {  
             prevPtr = prevPtr->nextPtr;  
         }  
         prevPtr->nextPtr = imagePtr->nextPtr;  
     }  
     ckfree((char *) imagePtr);  
   
     /*  
      * If there are no more instances left for the master, and if the  
      * master image has been deleted, then delete the master too.  
      */  
   
     if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) {  
         Tcl_DeleteHashEntry(masterPtr->hPtr);  
         ckfree((char *) masterPtr);  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_PostscriptImage --  
  *  
  *      This procedure is called by widgets that contain images in order  
  *      to redisplay an image on the screen or an off-screen pixmap.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The image's manager is notified, and it redraws the desired  
  *      portion of the image before returning.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass)  
     Tk_Image image;             /* Token for image to redisplay. */  
     Tcl_Interp *interp;  
     Tk_Window tkwin;  
     Tk_PostscriptInfo psinfo;   /* postscript info */  
     int x, y;                   /* Upper-left pixel of region in image that  
                                  * needs to be redisplayed. */  
     int width, height;          /* Dimensions of region to redraw. */  
     int prepass;  
 {  
     Image *imagePtr = (Image *) image;  
     int result;  
     XImage *ximage;  
     Pixmap pmap;  
     GC newGC;  
     XGCValues gcValues;  
   
     if (imagePtr->masterPtr->typePtr == NULL) {  
         /*  
          * No master for image, so nothing to display on postscript.  
          */  
         return TCL_OK;  
     }  
   
     /*  
      * Check if an image specific postscript-generation function  
      * exists; otherwise go on with generic code.  
      */  
   
     if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) {  
         return (*imagePtr->masterPtr->typePtr->postscriptProc)(  
             imagePtr->masterPtr->masterData, interp, tkwin, psinfo,  
             x, y, width, height, prepass);  
     }  
   
     if (prepass) {  
         return TCL_OK;  
     }  
   
     /*  
      * Create a Pixmap, tell the image to redraw itself there, and then  
      * generate an XImage from the Pixmap.  We can then read pixel  
      * values out of the XImage.  
      */  
   
     pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),  
                         width, height, Tk_Depth(tkwin));  
   
     gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));  
     newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);  
     if (newGC != None) {  
         XFillRectangle(Tk_Display(tkwin), pmap, newGC,  
                 0, 0, (unsigned int)width, (unsigned int)height);  
         Tk_FreeGC(Tk_Display(tkwin), newGC);  
     }  
   
     Tk_RedrawImage(image, x, y, width, height, pmap, 0, 0);  
   
     ximage = XGetImage(Tk_Display(tkwin), pmap, 0, 0,  
             (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);  
   
     Tk_FreePixmap(Tk_Display(tkwin), pmap);  
       
     if (ximage == NULL) {  
         /* The XGetImage() function is apparently not  
          * implemented on this system. Just ignore it.  
          */  
         return TCL_OK;  
     }  
     result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y,  
             width, height);  
   
     XDestroyImage(ximage);  
     return result;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_RedrawImage --  
  *  
  *      This procedure is called by widgets that contain images in order  
  *      to redisplay an image on the screen or an off-screen pixmap.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The image's manager is notified, and it redraws the desired  
  *      portion of the image before returning.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 Tk_RedrawImage(image, imageX, imageY, width, height, drawable,  
         drawableX, drawableY)  
     Tk_Image image;             /* Token for image to redisplay. */  
     int imageX, imageY;         /* Upper-left pixel of region in image that  
                                  * needs to be redisplayed. */  
     int width, height;          /* Dimensions of region to redraw. */  
     Drawable drawable;          /* Drawable in which to display image  
                                  * (window or pixmap).  If this is a pixmap,  
                                  * it must have the same depth as the window  
                                  * used in the Tk_GetImage call for the  
                                  * image. */  
     int drawableX, drawableY;   /* Coordinates in drawable that correspond  
                                  * to imageX and imageY. */  
 {  
     Image *imagePtr = (Image *) image;  
   
     if (imagePtr->masterPtr->typePtr == NULL) {  
         /*  
          * No master for image, so nothing to display.  
          */  
   
         return;  
     }  
   
     /*  
      * Clip the redraw area to the area of the image.  
      */  
   
     if (imageX < 0) {  
         width += imageX;  
         drawableX -= imageX;  
         imageX = 0;  
     }  
     if (imageY < 0) {  
         height += imageY;  
         drawableY -= imageY;  
         imageY = 0;  
     }  
     if ((imageX + width) > imagePtr->masterPtr->width) {  
         width = imagePtr->masterPtr->width - imageX;  
     }  
     if ((imageY + height) > imagePtr->masterPtr->height) {  
         height = imagePtr->masterPtr->height - imageY;  
     }  
     (*imagePtr->masterPtr->typePtr->displayProc)(  
             imagePtr->instanceData, imagePtr->display, drawable,  
             imageX, imageY, width, height, drawableX, drawableY);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_SizeOfImage --  
  *  
  *      This procedure returns the current dimensions of an image.  
  *  
  * Results:  
  *      The width and height of the image are returned in *widthPtr  
  *      and *heightPtr.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 Tk_SizeOfImage(image, widthPtr, heightPtr)  
     Tk_Image image;             /* Token for image whose size is wanted. */  
     int *widthPtr;              /* Return width of image here. */  
     int *heightPtr;             /* Return height of image here. */  
 {  
     Image *imagePtr = (Image *) image;  
   
     *widthPtr = imagePtr->masterPtr->width;  
     *heightPtr = imagePtr->masterPtr->height;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_DeleteImage --  
  *  
  *      Given the name of an image, this procedure destroys the  
  *      image.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The image is destroyed; existing instances will display as  
  *      blank areas.  If no such image exists then the procedure does  
  *      nothing.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 Tk_DeleteImage(interp, name)  
     Tcl_Interp *interp;         /* Interpreter in which the image was  
                                  * created. */  
     char *name;                 /* Name of image. */  
 {  
     Tcl_HashEntry *hPtr;  
     TkWindow *winPtr;  
   
     winPtr = (TkWindow *) Tk_MainWindow(interp);  
     if (winPtr == NULL) {  
         return;  
     }  
     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);  
     if (hPtr == NULL) {  
         return;  
     }  
     DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr));  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * DeleteImage --  
  *  
  *      This procedure is responsible for deleting an image.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The connection is dropped between instances of this image and  
  *      an image master.  Image instances will redisplay themselves  
  *      as empty areas, but existing instances will not be deleted.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 DeleteImage(masterPtr)  
     ImageMaster *masterPtr;     /* Pointer to main data structure for image. */  
 {  
     Image *imagePtr;  
     Tk_ImageType *typePtr;  
   
     typePtr = masterPtr->typePtr;  
     masterPtr->typePtr = NULL;  
     if (typePtr != NULL) {  
         for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;  
                 imagePtr = imagePtr->nextPtr) {  
            (*typePtr->freeProc)(imagePtr->instanceData,  
                    imagePtr->display);  
            (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,  
                     masterPtr->width, masterPtr->height, masterPtr->width,  
                     masterPtr->height);  
         }  
         (*typePtr->deleteProc)(masterPtr->masterData);  
     }  
     if (masterPtr->instancePtr == NULL) {  
         Tcl_DeleteHashEntry(masterPtr->hPtr);  
         ckfree((char *) masterPtr);  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkDeleteAllImages --  
  *  
  *      This procedure is called when an application is deleted.  It  
  *      calls back all of the managers for all images so that they  
  *      can cleanup, then it deletes all of Tk's internal information  
  *      about images.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      All information for all images gets deleted.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkDeleteAllImages(mainPtr)  
     TkMainInfo *mainPtr;        /* Structure describing application that is  
                                  * going away. */  
 {  
     Tcl_HashSearch search;  
     Tcl_HashEntry *hPtr;  
     ImageMaster *masterPtr;  
   
     for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);  
             hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {  
         masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);  
         DeleteImage(masterPtr);  
     }  
     Tcl_DeleteHashTable(&mainPtr->imageTable);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_GetImageMasterData --  
  *  
  *      Given the name of an image, this procedure returns the type  
  *      of the image and the clientData associated with its master.  
  *  
  * Results:  
  *      If there is no image by the given name, then NULL is returned  
  *      and a NULL value is stored at *typePtrPtr.  Otherwise the return  
  *      value is the clientData returned by the createProc when the  
  *      image was created and a pointer to the type structure for the  
  *      image is stored at *typePtrPtr.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 ClientData  
 Tk_GetImageMasterData(interp, name, typePtrPtr)  
     Tcl_Interp *interp;         /* Interpreter in which the image was  
                                  * created. */  
     char *name;                 /* Name of image. */  
     Tk_ImageType **typePtrPtr;  /* Points to location to fill in with  
                                  * pointer to type information for image. */  
 {  
     Tcl_HashEntry *hPtr;  
     TkWindow *winPtr;  
     ImageMaster *masterPtr;  
   
     winPtr = (TkWindow *) Tk_MainWindow(interp);  
     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);  
     if (hPtr == NULL) {  
         *typePtrPtr = NULL;  
         return NULL;  
     }  
     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);  
     *typePtrPtr = masterPtr->typePtr;  
     return masterPtr->masterData;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_SetTSOrigin --  
  *  
  *      Set the pattern origin of the tile to a common point (i.e. the  
  *      origin (0,0) of the top level window) so that tiles from two  
  *      different widgets will match up.  This done by setting the  
  *      GCTileStipOrigin field is set to the translated origin of the  
  *      toplevel window in the hierarchy.  
  *  
  * Results:  
  *      None.  
  *  
  * Side Effects:  
  *      The GCTileStipOrigin is reset in the GC.  This will cause the  
  *      tile origin to change when the GC is used for drawing.  
  *  
  *----------------------------------------------------------------------  
  */  
 /*ARGSUSED*/  
 void  
 Tk_SetTSOrigin(tkwin, gc, x, y)  
     Tk_Window tkwin;  
     GC gc;  
     int x, y;  
 {  
     while (!Tk_IsTopLevel(tkwin)) {  
         x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;  
         y -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;  
         tkwin = Tk_Parent(tkwin);  
     }  
     XSetTSOrigin(Tk_Display(tkwin), gc, x, y);  
 }  
   
   
 /* $History: tkImage.c $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 2:55a  
  * Created in $/IjuScripter, IjuConsole/Source/Tk Base  
  * Initial check-in.  
  */  
   
 /* End of TKIMAGE.C */  
1    /* $Header$ */
2    
3    /*
4     * tkImage.c --
5     *
6     *      This module implements the image protocol, which allows lots
7     *      of different kinds of images to be used in lots of different
8     *      widgets.
9     *
10     * Copyright (c) 1994 The Regents of the University of California.
11     * Copyright (c) 1994-1997 Sun Microsystems, Inc.
12     *
13     * See the file "license.terms" for information on usage and redistribution
14     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15     *
16     * RCS: @(#) $Id: tkimage.c,v 1.1.1.1 2001/06/13 05:02:12 dtashley Exp $
17     */
18    
19    #include "tkInt.h"
20    #include "tkPort.h"
21    
22    /*
23     * Each call to Tk_GetImage returns a pointer to one of the following
24     * structures, which is used as a token by clients (widgets) that
25     * display images.
26     */
27    
28    typedef struct Image {
29        Tk_Window tkwin;            /* Window passed to Tk_GetImage (needed to
30                                     * "re-get" the image later if the manager
31                                     * changes). */
32        Display *display;           /* Display for tkwin.  Needed because when
33                                     * the image is eventually freed tkwin may
34                                     * not exist anymore. */
35        struct ImageMaster *masterPtr;
36                                    /* Master for this image (identifiers image
37                                     * manager, for example). */
38        ClientData instanceData;
39                                    /* One word argument to pass to image manager
40                                     * when dealing with this image instance. */
41        Tk_ImageChangedProc *changeProc;
42                                    /* Code in widget to call when image changes
43                                     * in a way that affects redisplay. */
44        ClientData widgetClientData;
45                                    /* Argument to pass to changeProc. */
46        struct Image *nextPtr;      /* Next in list of all image instances
47                                     * associated with the same name. */
48    
49    } Image;
50    
51    /*
52     * For each image master there is one of the following structures,
53     * which represents a name in the image table and all of the images
54     * instantiated from it.  Entries in mainPtr->imageTable point to
55     * these structures.
56     */
57    
58    typedef struct ImageMaster {
59        Tk_ImageType *typePtr;      /* Information about image type.  NULL means
60                                     * that no image manager owns this image:  the
61                                     * image was deleted. */
62        ClientData masterData;      /* One-word argument to pass to image mgr
63                                     * when dealing with the master, as opposed
64                                     * to instances. */
65        int width, height;          /* Last known dimensions for image. */
66        Tcl_HashTable *tablePtr;    /* Pointer to hash table containing image
67                                     * (the imageTable field in some TkMainInfo
68                                     * structure). */
69        Tcl_HashEntry *hPtr;        /* Hash entry in mainPtr->imageTable for
70                                     * this structure (used to delete the hash
71                                     * entry). */
72        Image *instancePtr;         /* Pointer to first in list of instances
73                                     * derived from this name. */
74    } ImageMaster;
75    
76    typedef struct ThreadSpecificData {
77        Tk_ImageType *imageTypeList;/* First in a list of all known image
78                                     * types. */  
79        Tk_ImageType *oldImageTypeList;/* First in a list of all known old-style image
80                                     * types. */  
81    } ThreadSpecificData;          
82    static Tcl_ThreadDataKey dataKey;
83    
84    /*
85     * Prototypes for local procedures:
86     */
87    
88    static void             DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));
89    
90    /*
91     *----------------------------------------------------------------------
92     *
93     * Tk_CreateOldImageType, Tk_CreateImageType --
94     *
95     *      This procedure is invoked by an image manager to tell Tk about
96     *      a new kind of image and the procedures that manage the new type.
97     *      The procedure is typically invoked during Tcl_AppInit.
98     *
99     * Results:
100     *      None.
101     *
102     * Side effects:
103     *      The new image type is entered into a table used in the "image
104     *      create" command.
105     *
106     *----------------------------------------------------------------------
107     */
108    
109    void
110    Tk_CreateOldImageType(typePtr)
111        Tk_ImageType *typePtr;      /* Structure describing the type.  All of
112                                     * the fields except "nextPtr" must be filled
113                                     * in by caller.  Must not have been passed
114                                     * to Tk_CreateImageType previously. */
115    {
116        ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
117                Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
118    
119        typePtr->nextPtr = tsdPtr->oldImageTypeList;
120        tsdPtr->oldImageTypeList = typePtr;
121    }
122    
123    void
124    Tk_CreateImageType(typePtr)
125        Tk_ImageType *typePtr;      /* Structure describing the type.  All of
126                                     * the fields except "nextPtr" must be filled
127                                     * in by caller.  Must not have been passed
128                                     * to Tk_CreateImageType previously. */
129    {
130        ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
131                Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
132    
133        typePtr->nextPtr = tsdPtr->imageTypeList;
134        tsdPtr->imageTypeList = typePtr;
135    }
136    
137    /*
138     *----------------------------------------------------------------------
139     *
140     * Tk_ImageObjCmd --
141     *
142     *      This procedure is invoked to process the "image" Tcl command.
143     *      See the user documentation for details on what it does.
144     *
145     * Results:
146     *      A standard Tcl result.
147     *
148     * Side effects:
149     *      See the user documentation.
150     *
151     *----------------------------------------------------------------------
152     */
153    
154    int
155    Tk_ImageObjCmd(clientData, interp, objc, objv)
156        ClientData clientData;      /* Main window associated with interpreter. */
157        Tcl_Interp *interp;         /* Current interpreter. */
158        int objc;                   /* Number of arguments. */
159        Tcl_Obj *CONST objv[];      /* Argument strings. */
160    {
161        static char *imageOptions[] = {
162            "create", "delete", "height", "names", "type", "types", "width",
163            (char *) NULL
164        };
165        enum options {
166            IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_NAMES,
167            IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH
168        };
169        TkWindow *winPtr = (TkWindow *) clientData;
170        int i, new, firstOption,  index;
171        Tk_ImageType *typePtr;
172        ImageMaster *masterPtr;
173        Image *imagePtr;
174        Tcl_HashEntry *hPtr;
175        Tcl_HashSearch search;
176        char idString[16 + TCL_INTEGER_SPACE], *name;
177        TkDisplay *dispPtr = winPtr->dispPtr;
178        ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
179                Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
180    
181        if (objc < 2) {
182            Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
183            return TCL_ERROR;
184        }
185    
186        if (Tcl_GetIndexFromObj(interp, objv[1], imageOptions, "option", 0,
187                &index) != TCL_OK) {
188            return TCL_ERROR;
189        }
190        switch ((enum options) index) {
191            case IMAGE_CREATE: {
192                char *arg;
193                Tcl_Obj **args;
194                int oldimage = 0;
195                if (objc < 3) {
196                    Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?");
197                    return TCL_ERROR;
198                }
199    
200                /*
201                 * Look up the image type.
202                 */
203    
204                arg = Tcl_GetString(objv[2]);
205                for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
206                     typePtr = typePtr->nextPtr) {
207                    if ((*arg == typePtr->name[0])
208                            && (strcmp(arg, typePtr->name) == 0)) {
209                        break;
210                    }
211                }
212                if (typePtr == NULL) {
213                    oldimage = 1;
214                    for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
215                         typePtr = typePtr->nextPtr) {
216                        if ((*arg == typePtr->name[0])
217                                && (strcmp(arg, typePtr->name) == 0)) {
218                            break;
219                        }
220                    }
221                }
222                if (typePtr == NULL) {
223                    Tcl_AppendResult(interp, "image type \"", arg,
224                            "\" doesn't exist", (char *) NULL);
225                    return TCL_ERROR;
226                }
227    
228                /*
229                 * Figure out a name to use for the new image.
230                 */
231    
232                if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) {
233                    dispPtr->imageId++;
234                    sprintf(idString, "image%d", dispPtr->imageId);
235                    name = idString;
236                    firstOption = 3;
237                } else {
238                    name = arg;
239                    firstOption = 4;
240                }
241    
242                /*
243                 * Create the data structure for the new image.
244                 */
245    
246                hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable,
247                        name, &new);
248                if (new) {
249                    masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster));
250                    masterPtr->typePtr = NULL;
251                    masterPtr->masterData = NULL;
252                    masterPtr->width = masterPtr->height = 1;
253                    masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
254                    masterPtr->hPtr = hPtr;
255                    masterPtr->instancePtr = NULL;
256                    Tcl_SetHashValue(hPtr, masterPtr);
257                } else {
258                    /*
259                     * An image already exists by this name.  Disconnect the
260                     * instances from the master.
261                     */
262    
263                    masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
264                    if (masterPtr->typePtr != NULL) {
265                        for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
266                             imagePtr = imagePtr->nextPtr) {
267                            (*masterPtr->typePtr->freeProc)(
268                                imagePtr->instanceData, imagePtr->display);
269                            (*imagePtr->changeProc)(imagePtr->widgetClientData,
270                                    0, 0, masterPtr->width, masterPtr->height,
271                                    masterPtr->width, masterPtr->height);
272                        }
273                        (*masterPtr->typePtr->deleteProc)(masterPtr->masterData);
274                        masterPtr->typePtr = NULL;
275                    }
276                }
277    
278                /*
279                 * Call the image type manager so that it can perform its own
280                 * initialization, then re-"get" for any existing instances of
281                 * the image.
282                 */
283    
284                objv += firstOption;
285                objc -= firstOption;
286                args = (Tcl_Obj **) objv;
287                if (oldimage) {
288                    int i;
289                    args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *));
290                    for (i = 0; i < objc; i++) {
291                        args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]);
292                    }
293                    args[objc] = NULL;
294                }
295                if ((*typePtr->createProc)(interp, name, objc,
296                        args, typePtr, (Tk_ImageMaster) masterPtr,
297                        &masterPtr->masterData) != TCL_OK) {
298                    DeleteImage(masterPtr);
299                    if (oldimage) {
300                        ckfree((char *) args);
301                    }
302                    return TCL_ERROR;
303                }
304                if (oldimage) {
305                    ckfree((char *) args);
306                }
307                masterPtr->typePtr = typePtr;
308                for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
309                     imagePtr = imagePtr->nextPtr) {
310                    imagePtr->instanceData = (*typePtr->getProc)(
311                        imagePtr->tkwin, masterPtr->masterData);
312                }
313                Tcl_SetResult(interp,
314                        Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr),
315                        TCL_STATIC);
316                break;
317            }
318            case IMAGE_DELETE: {
319                for (i = 2; i < objc; i++) {
320                    char *arg = Tcl_GetString(objv[i]);
321                    hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
322                    if (hPtr == NULL) {
323                        Tcl_AppendResult(interp, "image \"", arg,
324                                "\" doesn't exist", (char *) NULL);
325                        return TCL_ERROR;
326                    }
327                    masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
328                    DeleteImage(masterPtr);
329                }
330                break;
331            }
332            case IMAGE_HEIGHT: {    
333                char *arg;
334                if (objc != 3) {
335                    Tcl_WrongNumArgs(interp, 2, objv, "name");
336                    return TCL_ERROR;
337                }
338                arg = Tcl_GetString(objv[2]);
339                hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
340                if (hPtr == NULL) {
341                    Tcl_AppendResult(interp, "image \"", arg,
342                            "\" doesn't exist", (char *) NULL);
343                    return TCL_ERROR;
344                }
345                masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
346                Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height);
347                break;
348            }
349            case IMAGE_NAMES: {
350                if (objc != 2) {
351                    Tcl_WrongNumArgs(interp, 2, objv, NULL);
352                    return TCL_ERROR;
353                }
354                for (hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
355                     hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
356                    Tcl_AppendElement(interp, Tcl_GetHashKey(
357                        &winPtr->mainPtr->imageTable, hPtr));
358                }
359                break;
360            }
361            case IMAGE_TYPE: {
362                char *arg;
363                if (objc != 3) {
364                    Tcl_WrongNumArgs(interp, 2, objv, "name");
365                    return TCL_ERROR;
366                }
367                arg = Tcl_GetString(objv[2]);
368                hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
369                if (hPtr == NULL) {
370                    Tcl_AppendResult(interp, "image \"", arg,
371                            "\" doesn't exist", (char *) NULL);
372                    return TCL_ERROR;
373                }
374                masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
375                if (masterPtr->typePtr != NULL) {
376                    Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC);
377                }
378                break;
379            }
380            case IMAGE_TYPES: {
381                if (objc != 2) {
382                    Tcl_WrongNumArgs(interp, 2, objv, NULL);
383                    return TCL_ERROR;
384                }
385                for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
386                     typePtr = typePtr->nextPtr) {
387                    Tcl_AppendElement(interp, typePtr->name);
388                }
389                for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
390                     typePtr = typePtr->nextPtr) {
391                    Tcl_AppendElement(interp, typePtr->name);
392                }
393                break;
394            }
395            case IMAGE_WIDTH: {
396                char *arg;
397                if (objc != 3) {
398                    Tcl_WrongNumArgs(interp, 2, objv, "name");
399                    return TCL_ERROR;
400                }
401                arg = Tcl_GetString(objv[2]);
402                hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
403                if (hPtr == NULL) {
404                    Tcl_AppendResult(interp, "image \"", arg,
405                            "\" doesn't exist", (char *) NULL);
406                    return TCL_ERROR;
407                }
408                masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
409                Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width);
410                break;
411            }
412        }
413        return TCL_OK;
414    }
415    
416    /*
417     *----------------------------------------------------------------------
418     *
419     * Tk_ImageChanged --
420     *
421     *      This procedure is called by an image manager whenever something
422     *      has happened that requires the image to be redrawn (some of its
423     *      pixels have changed, or its size has changed).
424     *
425     * Results:
426     *      None.
427     *
428     * Side effects:
429     *      Any widgets that display the image are notified so that they
430     *      can redisplay themselves as appropriate.
431     *
432     *----------------------------------------------------------------------
433     */
434    
435    void
436    Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth,
437            imageHeight)
438        Tk_ImageMaster imageMaster; /* Image that needs redisplay. */
439        int x, y;                   /* Coordinates of upper-left pixel of
440                                     * region of image that needs to be
441                                     * redrawn. */
442        int width, height;          /* Dimensions (in pixels) of region of
443                                     * image to redraw.  If either dimension
444                                     * is zero then the image doesn't need to
445                                     * be redrawn (perhaps all that happened is
446                                     * that its size changed). */
447        int imageWidth, imageHeight;/* New dimensions of image. */
448    {
449        ImageMaster *masterPtr = (ImageMaster *) imageMaster;
450        Image *imagePtr;
451    
452        masterPtr->width = imageWidth;
453        masterPtr->height = imageHeight;
454        for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
455             imagePtr = imagePtr->nextPtr) {
456            (*imagePtr->changeProc)(imagePtr->widgetClientData, x, y,
457                    width, height, imageWidth, imageHeight);
458        }
459    }
460    
461    /*
462     *----------------------------------------------------------------------
463     *
464     * Tk_NameOfImage --
465     *
466     *      Given a token for an image master, this procedure returns
467     *      the name of the image.
468     *
469     * Results:
470     *      The return value is the string name for imageMaster.
471     *
472     * Side effects:
473     *      None.
474     *
475     *----------------------------------------------------------------------
476     */
477    
478    char *
479    Tk_NameOfImage(imageMaster)
480        Tk_ImageMaster imageMaster;         /* Token for image. */
481    {
482        ImageMaster *masterPtr = (ImageMaster *) imageMaster;
483    
484        return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr);
485    }
486    
487    /*
488     *----------------------------------------------------------------------
489     *
490     * Tk_GetImage --
491     *
492     *      This procedure is invoked by a widget when it wants to use
493     *      a particular image in a particular window.
494     *
495     * Results:
496     *      The return value is a token for the image.  If there is no image
497     *      by the given name, then NULL is returned and an error message is
498     *      left in the interp's result.
499     *
500     * Side effects:
501     *      Tk records the fact that the widget is using the image, and
502     *      it will invoke changeProc later if the widget needs redisplay
503     *      (i.e. its size changes or some of its pixels change).  The
504     *      caller must eventually invoke Tk_FreeImage when it no longer
505     *      needs the image.
506     *
507     *----------------------------------------------------------------------
508     */
509    
510    Tk_Image
511    Tk_GetImage(interp, tkwin, name, changeProc, clientData)
512        Tcl_Interp *interp;         /* Place to leave error message if image
513                                     * can't be found. */
514        Tk_Window tkwin;            /* Token for window in which image will
515                                     * be used. */
516        char *name;                 /* Name of desired image. */
517        Tk_ImageChangedProc *changeProc;
518                                    /* Procedure to invoke when redisplay is
519                                     * needed because image's pixels or size
520                                     * changed. */
521        ClientData clientData;      /* One-word argument to pass to damageProc. */
522    {
523        Tcl_HashEntry *hPtr;
524        ImageMaster *masterPtr;
525        Image *imagePtr;
526    
527        hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);
528        if (hPtr == NULL) {
529            goto noSuchImage;
530        }
531        masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
532        if (masterPtr->typePtr == NULL) {
533            goto noSuchImage;
534        }
535        imagePtr = (Image *) ckalloc(sizeof(Image));
536        imagePtr->tkwin = tkwin;
537        imagePtr->display = Tk_Display(tkwin);
538        imagePtr->masterPtr = masterPtr;
539        imagePtr->instanceData =
540                (*masterPtr->typePtr->getProc)(tkwin, masterPtr->masterData);
541        imagePtr->changeProc = changeProc;
542        imagePtr->widgetClientData = clientData;
543        imagePtr->nextPtr = masterPtr->instancePtr;
544        masterPtr->instancePtr = imagePtr;
545        return (Tk_Image) imagePtr;
546    
547        noSuchImage:
548        Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist",
549                (char *) NULL);
550        return NULL;
551    }
552    
553    /*
554     *----------------------------------------------------------------------
555     *
556     * Tk_FreeImage --
557     *
558     *      This procedure is invoked by a widget when it no longer needs
559     *      an image acquired by a previous call to Tk_GetImage.  For each
560     *      call to Tk_GetImage there must be exactly one call to Tk_FreeImage.
561     *
562     * Results:
563     *      None.
564     *
565     * Side effects:
566     *      The association between the image and the widget is removed.
567     *
568     *----------------------------------------------------------------------
569     */
570    
571    void
572    Tk_FreeImage(image)
573        Tk_Image image;             /* Token for image that is no longer
574                                     * needed by a widget. */
575    {
576        Image *imagePtr = (Image *) image;
577        ImageMaster *masterPtr = imagePtr->masterPtr;
578        Image *prevPtr;
579    
580        /*
581         * Clean up the particular instance.
582         */
583    
584        if (masterPtr->typePtr != NULL) {
585            (*masterPtr->typePtr->freeProc)(imagePtr->instanceData,
586                    imagePtr->display);
587        }
588        prevPtr = masterPtr->instancePtr;
589        if (prevPtr == imagePtr) {
590            masterPtr->instancePtr = imagePtr->nextPtr;
591        } else {
592            while (prevPtr->nextPtr != imagePtr) {
593                prevPtr = prevPtr->nextPtr;
594            }
595            prevPtr->nextPtr = imagePtr->nextPtr;
596        }
597        ckfree((char *) imagePtr);
598    
599        /*
600         * If there are no more instances left for the master, and if the
601         * master image has been deleted, then delete the master too.
602         */
603    
604        if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) {
605            Tcl_DeleteHashEntry(masterPtr->hPtr);
606            ckfree((char *) masterPtr);
607        }
608    }
609    
610    /*
611     *----------------------------------------------------------------------
612     *
613     * Tk_PostscriptImage --
614     *
615     *      This procedure is called by widgets that contain images in order
616     *      to redisplay an image on the screen or an off-screen pixmap.
617     *
618     * Results:
619     *      None.
620     *
621     * Side effects:
622     *      The image's manager is notified, and it redraws the desired
623     *      portion of the image before returning.
624     *
625     *----------------------------------------------------------------------
626     */
627    
628    int
629    Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass)
630        Tk_Image image;             /* Token for image to redisplay. */
631        Tcl_Interp *interp;
632        Tk_Window tkwin;
633        Tk_PostscriptInfo psinfo;   /* postscript info */
634        int x, y;                   /* Upper-left pixel of region in image that
635                                     * needs to be redisplayed. */
636        int width, height;          /* Dimensions of region to redraw. */
637        int prepass;
638    {
639        Image *imagePtr = (Image *) image;
640        int result;
641        XImage *ximage;
642        Pixmap pmap;
643        GC newGC;
644        XGCValues gcValues;
645    
646        if (imagePtr->masterPtr->typePtr == NULL) {
647            /*
648             * No master for image, so nothing to display on postscript.
649             */
650            return TCL_OK;
651        }
652    
653        /*
654         * Check if an image specific postscript-generation function
655         * exists; otherwise go on with generic code.
656         */
657    
658        if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) {
659            return (*imagePtr->masterPtr->typePtr->postscriptProc)(
660                imagePtr->masterPtr->masterData, interp, tkwin, psinfo,
661                x, y, width, height, prepass);
662        }
663    
664        if (prepass) {
665            return TCL_OK;
666        }
667    
668        /*
669         * Create a Pixmap, tell the image to redraw itself there, and then
670         * generate an XImage from the Pixmap.  We can then read pixel
671         * values out of the XImage.
672         */
673    
674        pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
675                            width, height, Tk_Depth(tkwin));
676    
677        gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
678        newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
679        if (newGC != None) {
680            XFillRectangle(Tk_Display(tkwin), pmap, newGC,
681                    0, 0, (unsigned int)width, (unsigned int)height);
682            Tk_FreeGC(Tk_Display(tkwin), newGC);
683        }
684    
685        Tk_RedrawImage(image, x, y, width, height, pmap, 0, 0);
686    
687        ximage = XGetImage(Tk_Display(tkwin), pmap, 0, 0,
688                (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
689    
690        Tk_FreePixmap(Tk_Display(tkwin), pmap);
691        
692        if (ximage == NULL) {
693            /* The XGetImage() function is apparently not
694             * implemented on this system. Just ignore it.
695             */
696            return TCL_OK;
697        }
698        result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y,
699                width, height);
700    
701        XDestroyImage(ximage);
702        return result;
703    }
704    
705    /*
706     *----------------------------------------------------------------------
707     *
708     * Tk_RedrawImage --
709     *
710     *      This procedure is called by widgets that contain images in order
711     *      to redisplay an image on the screen or an off-screen pixmap.
712     *
713     * Results:
714     *      None.
715     *
716     * Side effects:
717     *      The image's manager is notified, and it redraws the desired
718     *      portion of the image before returning.
719     *
720     *----------------------------------------------------------------------
721     */
722    
723    void
724    Tk_RedrawImage(image, imageX, imageY, width, height, drawable,
725            drawableX, drawableY)
726        Tk_Image image;             /* Token for image to redisplay. */
727        int imageX, imageY;         /* Upper-left pixel of region in image that
728                                     * needs to be redisplayed. */
729        int width, height;          /* Dimensions of region to redraw. */
730        Drawable drawable;          /* Drawable in which to display image
731                                     * (window or pixmap).  If this is a pixmap,
732                                     * it must have the same depth as the window
733                                     * used in the Tk_GetImage call for the
734                                     * image. */
735        int drawableX, drawableY;   /* Coordinates in drawable that correspond
736                                     * to imageX and imageY. */
737    {
738        Image *imagePtr = (Image *) image;
739    
740        if (imagePtr->masterPtr->typePtr == NULL) {
741            /*
742             * No master for image, so nothing to display.
743             */
744    
745            return;
746        }
747    
748        /*
749         * Clip the redraw area to the area of the image.
750         */
751    
752        if (imageX < 0) {
753            width += imageX;
754            drawableX -= imageX;
755            imageX = 0;
756        }
757        if (imageY < 0) {
758            height += imageY;
759            drawableY -= imageY;
760            imageY = 0;
761        }
762        if ((imageX + width) > imagePtr->masterPtr->width) {
763            width = imagePtr->masterPtr->width - imageX;
764        }
765        if ((imageY + height) > imagePtr->masterPtr->height) {
766            height = imagePtr->masterPtr->height - imageY;
767        }
768        (*imagePtr->masterPtr->typePtr->displayProc)(
769                imagePtr->instanceData, imagePtr->display, drawable,
770                imageX, imageY, width, height, drawableX, drawableY);
771    }
772    
773    /*
774     *----------------------------------------------------------------------
775     *
776     * Tk_SizeOfImage --
777     *
778     *      This procedure returns the current dimensions of an image.
779     *
780     * Results:
781     *      The width and height of the image are returned in *widthPtr
782     *      and *heightPtr.
783     *
784     * Side effects:
785     *      None.
786     *
787     *----------------------------------------------------------------------
788     */
789    
790    void
791    Tk_SizeOfImage(image, widthPtr, heightPtr)
792        Tk_Image image;             /* Token for image whose size is wanted. */
793        int *widthPtr;              /* Return width of image here. */
794        int *heightPtr;             /* Return height of image here. */
795    {
796        Image *imagePtr = (Image *) image;
797    
798        *widthPtr = imagePtr->masterPtr->width;
799        *heightPtr = imagePtr->masterPtr->height;
800    }
801    
802    /*
803     *----------------------------------------------------------------------
804     *
805     * Tk_DeleteImage --
806     *
807     *      Given the name of an image, this procedure destroys the
808     *      image.
809     *
810     * Results:
811     *      None.
812     *
813     * Side effects:
814     *      The image is destroyed; existing instances will display as
815     *      blank areas.  If no such image exists then the procedure does
816     *      nothing.
817     *
818     *----------------------------------------------------------------------
819     */
820    
821    void
822    Tk_DeleteImage(interp, name)
823        Tcl_Interp *interp;         /* Interpreter in which the image was
824                                     * created. */
825        char *name;                 /* Name of image. */
826    {
827        Tcl_HashEntry *hPtr;
828        TkWindow *winPtr;
829    
830        winPtr = (TkWindow *) Tk_MainWindow(interp);
831        if (winPtr == NULL) {
832            return;
833        }
834        hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
835        if (hPtr == NULL) {
836            return;
837        }
838        DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr));
839    }
840    
841    /*
842     *----------------------------------------------------------------------
843     *
844     * DeleteImage --
845     *
846     *      This procedure is responsible for deleting an image.
847     *
848     * Results:
849     *      None.
850     *
851     * Side effects:
852     *      The connection is dropped between instances of this image and
853     *      an image master.  Image instances will redisplay themselves
854     *      as empty areas, but existing instances will not be deleted.
855     *
856     *----------------------------------------------------------------------
857     */
858    
859    static void
860    DeleteImage(masterPtr)
861        ImageMaster *masterPtr;     /* Pointer to main data structure for image. */
862    {
863        Image *imagePtr;
864        Tk_ImageType *typePtr;
865    
866        typePtr = masterPtr->typePtr;
867        masterPtr->typePtr = NULL;
868        if (typePtr != NULL) {
869            for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
870                    imagePtr = imagePtr->nextPtr) {
871               (*typePtr->freeProc)(imagePtr->instanceData,
872                       imagePtr->display);
873               (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,
874                        masterPtr->width, masterPtr->height, masterPtr->width,
875                        masterPtr->height);
876            }
877            (*typePtr->deleteProc)(masterPtr->masterData);
878        }
879        if (masterPtr->instancePtr == NULL) {
880            Tcl_DeleteHashEntry(masterPtr->hPtr);
881            ckfree((char *) masterPtr);
882        }
883    }
884    
885    /*
886     *----------------------------------------------------------------------
887     *
888     * TkDeleteAllImages --
889     *
890     *      This procedure is called when an application is deleted.  It
891     *      calls back all of the managers for all images so that they
892     *      can cleanup, then it deletes all of Tk's internal information
893     *      about images.
894     *
895     * Results:
896     *      None.
897     *
898     * Side effects:
899     *      All information for all images gets deleted.
900     *
901     *----------------------------------------------------------------------
902     */
903    
904    void
905    TkDeleteAllImages(mainPtr)
906        TkMainInfo *mainPtr;        /* Structure describing application that is
907                                     * going away. */
908    {
909        Tcl_HashSearch search;
910        Tcl_HashEntry *hPtr;
911        ImageMaster *masterPtr;
912    
913        for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);
914                hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
915            masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
916            DeleteImage(masterPtr);
917        }
918        Tcl_DeleteHashTable(&mainPtr->imageTable);
919    }
920    
921    /*
922     *----------------------------------------------------------------------
923     *
924     * Tk_GetImageMasterData --
925     *
926     *      Given the name of an image, this procedure returns the type
927     *      of the image and the clientData associated with its master.
928     *
929     * Results:
930     *      If there is no image by the given name, then NULL is returned
931     *      and a NULL value is stored at *typePtrPtr.  Otherwise the return
932     *      value is the clientData returned by the createProc when the
933     *      image was created and a pointer to the type structure for the
934     *      image is stored at *typePtrPtr.
935     *
936     * Side effects:
937     *      None.
938     *
939     *----------------------------------------------------------------------
940     */
941    
942    ClientData
943    Tk_GetImageMasterData(interp, name, typePtrPtr)
944        Tcl_Interp *interp;         /* Interpreter in which the image was
945                                     * created. */
946        char *name;                 /* Name of image. */
947        Tk_ImageType **typePtrPtr;  /* Points to location to fill in with
948                                     * pointer to type information for image. */
949    {
950        Tcl_HashEntry *hPtr;
951        TkWindow *winPtr;
952        ImageMaster *masterPtr;
953    
954        winPtr = (TkWindow *) Tk_MainWindow(interp);
955        hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
956        if (hPtr == NULL) {
957            *typePtrPtr = NULL;
958            return NULL;
959        }
960        masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
961        *typePtrPtr = masterPtr->typePtr;
962        return masterPtr->masterData;
963    }
964    
965    /*
966     *----------------------------------------------------------------------
967     *
968     * Tk_SetTSOrigin --
969     *
970     *      Set the pattern origin of the tile to a common point (i.e. the
971     *      origin (0,0) of the top level window) so that tiles from two
972     *      different widgets will match up.  This done by setting the
973     *      GCTileStipOrigin field is set to the translated origin of the
974     *      toplevel window in the hierarchy.
975     *
976     * Results:
977     *      None.
978     *
979     * Side Effects:
980     *      The GCTileStipOrigin is reset in the GC.  This will cause the
981     *      tile origin to change when the GC is used for drawing.
982     *
983     *----------------------------------------------------------------------
984     */
985    /*ARGSUSED*/
986    void
987    Tk_SetTSOrigin(tkwin, gc, x, y)
988        Tk_Window tkwin;
989        GC gc;
990        int x, y;
991    {
992        while (!Tk_IsTopLevel(tkwin)) {
993            x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
994            y -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
995            tkwin = Tk_Parent(tkwin);
996        }
997        XSetTSOrigin(Tk_Display(tkwin), gc, x, y);
998    }
999    
1000    /* End of tkimage.c */

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25