📄 tkimgphoto.c
字号:
* Set configuration options and finish the initialization of the instance. */ ImgPhotoConfigureInstance(instancePtr); /* * If this is the first instance, must set the size of the image. */ if (instancePtr->nextPtr == NULL) { Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width, masterPtr->height); } /* * Dither the image to fill in this instance's pixmap. */ TkClipBox(masterPtr->validRegion, &validBox); if ((validBox.width > 0) && (validBox.height > 0)) { DitherInstance(instancePtr, validBox.x, validBox.y, validBox.width, validBox.height); } return (ClientData) instancePtr;}/* *---------------------------------------------------------------------- * * ImgPhotoDisplay -- * * This procedure is invoked to draw a photo image. * * Results: * None. * * Side effects: * A portion of the image gets rendered in a pixmap or window. * *---------------------------------------------------------------------- */static voidImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, height, drawableX, drawableY) ClientData clientData; /* Pointer to PhotoInstance structure for * for instance to be displayed. */ Display *display; /* Display on which to draw image. */ Drawable drawable; /* Pixmap or window in which to draw image. */ int imageX, imageY; /* Upper-left corner of region within image * to draw. */ int width, height; /* Dimensions of region within image to draw. */ int drawableX, drawableY; /* Coordinates within drawable that * correspond to imageX and imageY. */{ PhotoInstance *instancePtr = (PhotoInstance *) clientData; /* * If there's no pixmap, it means that an error occurred * while creating the image instance so it can't be displayed. */ if (instancePtr->pixels == None) { return; } /* * masterPtr->region describes which parts of the image contain * valid data. We set this region as the clip mask for the gc, * setting its origin appropriately, and use it when drawing the * image. */ TkSetRegion(display, instancePtr->gc, instancePtr->masterPtr->validRegion); XSetClipOrigin(display, instancePtr->gc, drawableX - imageX, drawableY - imageY); XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc, imageX, imageY, (unsigned) width, (unsigned) height, drawableX, drawableY); XSetClipMask(display, instancePtr->gc, None); XSetClipOrigin(display, instancePtr->gc, 0, 0);}/* *---------------------------------------------------------------------- * * ImgPhotoFree -- * * This procedure is called when a widget ceases to use a * particular instance of an image. We don't actually get * rid of the instance until later because we may be about * to get this instance again. * * Results: * None. * * Side effects: * Internal data structures get cleaned up, later. * *---------------------------------------------------------------------- */static voidImgPhotoFree(clientData, display) ClientData clientData; /* Pointer to PhotoInstance structure for * for instance to be displayed. */ Display *display; /* Display containing window that used image. */{ PhotoInstance *instancePtr = (PhotoInstance *) clientData; ColorTable *colorPtr; instancePtr->refCount -= 1; if (instancePtr->refCount > 0) { return; } /* * There are no more uses of the image within this widget. * Decrement the count of live uses of its color table, so * that its colors can be reclaimed if necessary, and * set up an idle call to free the instance structure. */ colorPtr = instancePtr->colorTablePtr; if (colorPtr != NULL) { colorPtr->liveRefCount -= 1; } Tcl_DoWhenIdle(DisposeInstance, (ClientData) instancePtr);}/* *---------------------------------------------------------------------- * * ImgPhotoDelete -- * * This procedure is called by the image code to delete the * master structure for an image. * * Results: * None. * * Side effects: * Resources associated with the image get freed. * *---------------------------------------------------------------------- */static voidImgPhotoDelete(masterData) ClientData masterData; /* Pointer to PhotoMaster structure for * image. Must not have any more instances. */{ PhotoMaster *masterPtr = (PhotoMaster *) masterData; PhotoInstance *instancePtr; while ((instancePtr = masterPtr->instancePtr) != NULL) { if (instancePtr->refCount > 0) { panic("tried to delete photo image when instances still exist"); } Tcl_CancelIdleCall(DisposeInstance, (ClientData) instancePtr); DisposeInstance((ClientData) instancePtr); } masterPtr->tkMaster = NULL; if (masterPtr->imageCmd != NULL) { Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd); } if (masterPtr->pix24 != NULL) { ckfree((char *) masterPtr->pix24); } if (masterPtr->validRegion != NULL) { TkDestroyRegion(masterPtr->validRegion); } Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0); ckfree((char *) masterPtr);}/* *---------------------------------------------------------------------- * * ImgPhotoCmdDeletedProc -- * * This procedure is invoked when the image command for an image * is deleted. It deletes the image. * * Results: * None. * * Side effects: * The image is deleted. * *---------------------------------------------------------------------- */static voidImgPhotoCmdDeletedProc(clientData) ClientData clientData; /* Pointer to PhotoMaster structure for * image. */{ PhotoMaster *masterPtr = (PhotoMaster *) clientData; masterPtr->imageCmd = NULL; if (masterPtr->tkMaster != NULL) { Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster)); }}/* *---------------------------------------------------------------------- * * ImgPhotoSetSize -- * * This procedure reallocates the image storage and instance * pixmaps for a photo image, as necessary, to change the * image's size to `width' x `height' pixels. * * Results: * None. * * Side effects: * Storage gets reallocated, for the master and all its instances. * *---------------------------------------------------------------------- */static voidImgPhotoSetSize(masterPtr, width, height) PhotoMaster *masterPtr; int width, height;{ unsigned char *newPix24; int h, offset, pitch; unsigned char *srcPtr, *destPtr; XRectangle validBox, clipBox; TkRegion clipRegion; PhotoInstance *instancePtr; if (masterPtr->userWidth > 0) { width = masterPtr->userWidth; } if (masterPtr->userHeight > 0) { height = masterPtr->userHeight; } /* * We have to trim the valid region if it is currently * larger than the new image size. */ TkClipBox(masterPtr->validRegion, &validBox); if ((validBox.x + validBox.width > width) || (validBox.y + validBox.height > height)) { clipBox.x = 0; clipBox.y = 0; clipBox.width = width; clipBox.height = height; clipRegion = TkCreateRegion(); TkUnionRectWithRegion(&clipBox, clipRegion, clipRegion); TkIntersectRegion(masterPtr->validRegion, clipRegion, masterPtr->validRegion); TkDestroyRegion(clipRegion); TkClipBox(masterPtr->validRegion, &validBox); } if ((width != masterPtr->width) || (height != masterPtr->height) || (masterPtr->pix24 == NULL)) { /* * Reallocate storage for the 24-bit image and copy * over valid regions. */ pitch = width * 3; newPix24 = (unsigned char *) ckalloc((unsigned) (height * pitch)); /* * Zero the new array. The dithering code shouldn't read the * areas outside validBox, but they might be copied to another * photo image or written to a file. */ if ((masterPtr->pix24 != NULL) && ((width == masterPtr->width) || (width == validBox.width))) { if (validBox.y > 0) { memset((VOID *) newPix24, 0, (size_t) (validBox.y * pitch)); } h = validBox.y + validBox.height; if (h < height) { memset((VOID *) (newPix24 + h * pitch), 0, (size_t) ((height - h) * pitch)); } } else { memset((VOID *) newPix24, 0, (size_t) (height * pitch)); } if (masterPtr->pix24 != NULL) { /* * Copy the common area over to the new array array and * free the old array. */ if (width == masterPtr->width) { /* * The region to be copied is contiguous. */ offset = validBox.y * pitch; memcpy((VOID *) (newPix24 + offset), (VOID *) (masterPtr->pix24 + offset), (size_t) (validBox.height * pitch)); } else if ((validBox.width > 0) && (validBox.height > 0)) { /* * Area to be copied is not contiguous - copy line by line. */ destPtr = newPix24 + (validBox.y * width + validBox.x) * 3; srcPtr = masterPtr->pix24 + (validBox.y * masterPtr->width + validBox.x) * 3; for (h = validBox.height; h > 0; h--) { memcpy((VOID *) destPtr, (VOID *) srcPtr, (size_t) (validBox.width * 3)); destPtr += width * 3; srcPtr += masterPtr->width * 3; } } ckfree((char *) masterPtr->pix24); } masterPtr->pix24 = newPix24; masterPtr->width = width; masterPtr->height = height; /* * Dithering will be correct up to the end of the last * pre-existing complete scanline. */ if ((validBox.x > 0) || (validBox.y > 0)) { masterPtr->ditherX = 0; masterPtr->ditherY = 0; } else if (validBox.width == width) { if ((int) validBox.height < masterPtr->ditherY) { masterPtr->ditherX = 0; masterPtr->ditherY = validBox.height; } } else { if ((masterPtr->ditherY > 0) || ((int) validBox.width < masterPtr->ditherX)) { masterPtr->ditherX = validBox.width; masterPtr->ditherY = 0; } } } /* * Now adjust the sizes of the pixmaps for all of the instances. */ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { ImgPhotoInstanceSetSize(instancePtr); }}/* *---------------------------------------------------------------------- * * ImgPhotoInstanceSetSize -- * * This procedure reallocates the instance pixmap and dithering * error array for a photo instance, as necessary, to change the * image's size to `width' x `height' pixels. * * Results: * None. * * Side effects: * Storage gets reallocated, here and in the X server. * *---------------------------------------------------------------------- */static voidImgPhotoInstanceSetSize(instancePtr) PhotoInstance *instancePtr; /* Instance whose size is to be * changed. */{ PhotoMaster *masterPtr; schar *newError; schar *errSrcPtr, *errDestPtr; int h, offset; XRectangle validBox; Pixmap newPixmap; masterPtr = instancePtr->masterPtr; TkClipBox(masterPtr->validRegion, &validBox); if ((instancePtr->width != masterPtr->width) || (instancePtr->height != masterPtr->height) || (instancePtr->pixels == None)) { newPixmap = Tk_GetPixmap(instancePtr->display, RootWindow(instancePtr->display, instancePtr->visualInfo.screen), (masterPtr->width > 0) ? masterPtr->width: 1, (masterPtr->height > 0) ? masterPtr->height: 1, instancePtr->visualInfo.depth); /* * The following is a gross hack needed to properly support colormaps * under Windows. Before the pixels can be copied to the pixmap, * the relevent colormap must be associated with the drawable. * Normally we can infer this association from the window that * was used to create the pixmap. However, in this case we're * using the root window, so we have to be more explicit. */ TkSetPixmapColormap(newPixmap, instancePtr->colormap); if (instancePtr->pixels != None) { /* * Copy any common pixels from the old pixmap and free it. */ XCopyArea(instancePtr->display, instancePtr->pixels, newPixmap, instancePtr->gc, validBox.x, validBox.y, validBox.width, validBox.height, validBox.x, validBox.y); Tk_FreePixmap(instancePtr->display, instancePtr->pixels); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -