📄 tkimage.c
字号:
/* * 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-1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tkImage.c 1.15 97/10/09 09:57:50 */#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;/* * The following variable points to the first in a list of all known * image types. */static Tk_ImageType *imageTypeList = NULL;/* * Prototypes for local procedures: */static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));/* *---------------------------------------------------------------------- * * 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. * *---------------------------------------------------------------------- */voidTk_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. */{ typePtr->nextPtr = imageTypeList; imageTypeList = typePtr;}/* *---------------------------------------------------------------------- * * Tk_ImageCmd -- * * 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. * *---------------------------------------------------------------------- */intTk_ImageCmd(clientData, interp, argc, argv) ClientData clientData; /* Main window associated with interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ TkWindow *winPtr = (TkWindow *) clientData; int c, i, new, firstOption; size_t length; Tk_ImageType *typePtr; ImageMaster *masterPtr; Image *imagePtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; char idString[30], *name; static int id = 0; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option ?args?\"", (char *) NULL); return TCL_ERROR; } c = argv[1][0]; length = strlen(argv[1]); if ((c == 'c') && (strncmp(argv[1], "create", length) == 0)) { if (argc < 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " create type ?name? ?options?\"", (char *) NULL); return TCL_ERROR; } c = argv[2][0]; /* * Look up the image type. */ for (typePtr = imageTypeList; typePtr != NULL; typePtr = typePtr->nextPtr) { if ((c == typePtr->name[0]) && (strcmp(argv[2], typePtr->name) == 0)) { break; } } if (typePtr == NULL) { Tcl_AppendResult(interp, "image type \"", argv[2], "\" doesn't exist", (char *) NULL); return TCL_ERROR; } /* * Figure out a name to use for the new image. */ if ((argc == 3) || (argv[3][0] == '-')) { id++; sprintf(idString, "image%d", id); name = idString; firstOption = 3; } else { name = argv[3]; 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. */ if ((*typePtr->createProc)(interp, name, argc-firstOption, argv+firstOption, typePtr, (Tk_ImageMaster) masterPtr, &masterPtr->masterData) != TCL_OK) { DeleteImage(masterPtr); return TCL_ERROR; } masterPtr->typePtr = typePtr; for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; imagePtr = imagePtr->nextPtr) { imagePtr->instanceData = (*typePtr->getProc)( imagePtr->tkwin, masterPtr->masterData); } interp->result = Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr); } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) { for (i = 2; i < argc; i++) { hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[i]); if (hPtr == NULL) { Tcl_AppendResult(interp, "image \"", argv[i], "\" doesn't exist", (char *) NULL); return TCL_ERROR; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); DeleteImage(masterPtr); } } else if ((c == 'h') && (strncmp(argv[1], "height", length) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " height name\"", (char *) NULL); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]); if (hPtr == NULL) { Tcl_AppendResult(interp, "image \"", argv[2], "\" doesn't exist", (char *) NULL); return TCL_ERROR; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); sprintf(interp->result, "%d", masterPtr->height); } else if ((c == 'n') && (strncmp(argv[1], "names", length) == 0)) { if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " names\"", (char *) 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)); } } else if ((c == 't') && (strcmp(argv[1], "type") == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " type name\"", (char *) NULL); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]); if (hPtr == NULL) { Tcl_AppendResult(interp, "image \"", argv[2], "\" doesn't exist", (char *) NULL); return TCL_ERROR; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); if (masterPtr->typePtr != NULL) { interp->result = masterPtr->typePtr->name; } } else if ((c == 't') && (strcmp(argv[1], "types") == 0)) { if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " types\"", (char *) NULL); return TCL_ERROR; } for (typePtr = imageTypeList; typePtr != NULL; typePtr = typePtr->nextPtr) { Tcl_AppendElement(interp, typePtr->name); } } else if ((c == 'w') && (strncmp(argv[1], "width", length) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " width name\"", (char *) NULL); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]); if (hPtr == NULL) { Tcl_AppendResult(interp, "image \"", argv[2], "\" doesn't exist", (char *) NULL); return TCL_ERROR; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); sprintf(interp->result, "%d", masterPtr->width); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create, delete, height, names, type, types,", " or width", (char *) NULL); return TCL_ERROR; } 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. * *---------------------------------------------------------------------- */voidTk_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. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -