📄 tkimgphoto.c
字号:
ckfree(masterPtr->fileString); masterPtr->fileString = NULL; } if ((masterPtr->dataString != NULL) && (masterPtr->dataString[0] == 0)) { ckfree(masterPtr->dataString); masterPtr->dataString = NULL; } if ((masterPtr->format != NULL) && (masterPtr->format[0] == 0)) { ckfree(masterPtr->format); masterPtr->format = NULL; } /* * Set the image to the user-requested size, if any, * and make sure storage is correctly allocated for this image. */ ImgPhotoSetSize(masterPtr, masterPtr->width, masterPtr->height); /* * Read in the image from the file or string if the user has * specified the -file or -data option. */ if ((masterPtr->fileString != NULL) && (masterPtr->fileString != oldFileString)) { /* * Prevent file system access in a safe interpreter. */ if (Tcl_IsSafe(interp)) { Tcl_AppendResult(interp, "can't get image from a file in a", " safe interpreter", (char *) NULL); return TCL_ERROR; } chan = Tcl_OpenFileChannel(interp, masterPtr->fileString, "r", 0); if (chan == NULL) { return TCL_ERROR; } if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) { return TCL_ERROR; } if (MatchFileFormat(interp, chan, masterPtr->fileString, masterPtr->format, &imageFormat, &imageWidth, &imageHeight) != TCL_OK) { Tcl_Close(NULL, chan); return TCL_ERROR; } ImgPhotoSetSize(masterPtr, imageWidth, imageHeight); result = (*imageFormat->fileReadProc)(interp, chan, masterPtr->fileString, masterPtr->format, (Tk_PhotoHandle) masterPtr, 0, 0, imageWidth, imageHeight, 0, 0); Tcl_Close(NULL, chan); if (result != TCL_OK) { return TCL_ERROR; } masterPtr->flags |= IMAGE_CHANGED; } if ((masterPtr->fileString == NULL) && (masterPtr->dataString != NULL) && (masterPtr->dataString != oldDataString)) { if (MatchStringFormat(interp, masterPtr->dataString, masterPtr->format, &imageFormat, &imageWidth, &imageHeight) != TCL_OK) { return TCL_ERROR; } ImgPhotoSetSize(masterPtr, imageWidth, imageHeight); if ((*imageFormat->stringReadProc)(interp, masterPtr->dataString, masterPtr->format, (Tk_PhotoHandle) masterPtr, 0, 0, imageWidth, imageHeight, 0, 0) != TCL_OK) { return TCL_ERROR; } masterPtr->flags |= IMAGE_CHANGED; } /* * Enforce a reasonable value for gamma. */ if (masterPtr->gamma <= 0) { masterPtr->gamma = 1.0; } if ((masterPtr->gamma != oldGamma) || (masterPtr->palette != oldPaletteString)) { masterPtr->flags |= IMAGE_CHANGED; } /* * Cycle through all of the instances of this image, regenerating * the information for each instance. Then force the image to be * redisplayed everywhere that it is used. */ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { ImgPhotoConfigureInstance(instancePtr); } /* * Inform the generic image code that the image * has (potentially) changed. */ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width, masterPtr->height, masterPtr->width, masterPtr->height); masterPtr->flags &= ~IMAGE_CHANGED; return TCL_OK;}/* *---------------------------------------------------------------------- * * ImgPhotoConfigureInstance -- * * This procedure is called to create displaying information for * a photo image instance based on the configuration information * in the master. It is invoked both when new instances are * created and when the master is reconfigured. * * Results: * None. * * Side effects: * Generates errors via Tcl_BackgroundError if there are problems * in setting up the instance. * *---------------------------------------------------------------------- */static voidImgPhotoConfigureInstance(instancePtr) PhotoInstance *instancePtr; /* Instance to reconfigure. */{ PhotoMaster *masterPtr = instancePtr->masterPtr; XImage *imagePtr; int bitsPerPixel; ColorTable *colorTablePtr; XRectangle validBox; /* * If the -palette configuration option has been set for the master, * use the value specified for our palette, but only if it is * a valid palette for our windows. Use the gamma value specified * the master. */ if ((masterPtr->palette && masterPtr->palette[0]) && IsValidPalette(instancePtr, masterPtr->palette)) { instancePtr->palette = masterPtr->palette; } else { instancePtr->palette = instancePtr->defaultPalette; } instancePtr->gamma = masterPtr->gamma; /* * If we don't currently have a color table, or if the one we * have no longer applies (e.g. because our palette or gamma * has changed), get a new one. */ colorTablePtr = instancePtr->colorTablePtr; if ((colorTablePtr == NULL) || (instancePtr->colormap != colorTablePtr->id.colormap) || (instancePtr->palette != colorTablePtr->id.palette) || (instancePtr->gamma != colorTablePtr->id.gamma)) { /* * Free up our old color table, and get a new one. */ if (colorTablePtr != NULL) { colorTablePtr->liveRefCount -= 1; FreeColorTable(colorTablePtr); } GetColorTable(instancePtr); /* * Create a new XImage structure for sending data to * the X server, if necessary. */ if (instancePtr->colorTablePtr->flags & BLACK_AND_WHITE) { bitsPerPixel = 1; } else { bitsPerPixel = instancePtr->visualInfo.depth; } if ((instancePtr->imagePtr == NULL) || (instancePtr->imagePtr->bits_per_pixel != bitsPerPixel)) { if (instancePtr->imagePtr != NULL) { XFree((char *) instancePtr->imagePtr); } imagePtr = XCreateImage(instancePtr->display, instancePtr->visualInfo.visual, (unsigned) bitsPerPixel, (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, (char *) NULL, 1, 1, 32, 0); instancePtr->imagePtr = imagePtr; /* * Determine the endianness of this machine. * We create images using the local host's endianness, rather * than the endianness of the server; otherwise we would have * to byte-swap any 16 or 32 bit values that we store in the * image in those situations where the server's endianness * is different from ours. */ if (imagePtr != NULL) { union { int i; char c[sizeof(int)]; } kludge; imagePtr->bitmap_unit = sizeof(pixel) * NBBY; kludge.i = 0; kludge.c[0] = 1; imagePtr->byte_order = (kludge.i == 1) ? LSBFirst : MSBFirst; _XInitImageFuncPtrs(imagePtr); } } } /* * If the user has specified a width and/or height for the master * which is different from our current width/height, set the size * to the values specified by the user. If we have no pixmap, we * do this also, since it has the side effect of allocating a * pixmap for us. */ if ((instancePtr->pixels == None) || (instancePtr->error == NULL) || (instancePtr->width != masterPtr->width) || (instancePtr->height != masterPtr->height)) { ImgPhotoInstanceSetSize(instancePtr); } /* * Redither this instance if necessary. */ if ((masterPtr->flags & IMAGE_CHANGED) || (instancePtr->colorTablePtr != colorTablePtr)) { TkClipBox(masterPtr->validRegion, &validBox); if ((validBox.width > 0) && (validBox.height > 0)) { DitherInstance(instancePtr, validBox.x, validBox.y, validBox.width, validBox.height); } }}/* *---------------------------------------------------------------------- * * ImgPhotoGet -- * * This procedure is called for each use of a photo image in a * widget. * * Results: * The return value is a token for the instance, which is passed * back to us in calls to ImgPhotoDisplay and ImgPhotoFree. * * Side effects: * A data structure is set up for the instance (or, an existing * instance is re-used for the new one). * *---------------------------------------------------------------------- */static ClientDataImgPhotoGet(tkwin, masterData) Tk_Window tkwin; /* Window in which the instance will be * used. */ ClientData masterData; /* Pointer to our master structure for the * image. */{ PhotoMaster *masterPtr = (PhotoMaster *) masterData; PhotoInstance *instancePtr; Colormap colormap; int mono, nRed, nGreen, nBlue; XVisualInfo visualInfo, *visInfoPtr; XRectangle validBox; char buf[16]; int numVisuals; XColor *white, *black; XGCValues gcValues; /* * Table of "best" choices for palette for PseudoColor displays * with between 3 and 15 bits/pixel. */ static int paletteChoice[13][3] = { /* #red, #green, #blue */ {2, 2, 2, /* 3 bits, 8 colors */}, {2, 3, 2, /* 4 bits, 12 colors */}, {3, 4, 2, /* 5 bits, 24 colors */}, {4, 5, 3, /* 6 bits, 60 colors */}, {5, 6, 4, /* 7 bits, 120 colors */}, {7, 7, 4, /* 8 bits, 198 colors */}, {8, 10, 6, /* 9 bits, 480 colors */}, {10, 12, 8, /* 10 bits, 960 colors */}, {14, 15, 9, /* 11 bits, 1890 colors */}, {16, 20, 12, /* 12 bits, 3840 colors */}, {20, 24, 16, /* 13 bits, 7680 colors */}, {26, 30, 20, /* 14 bits, 15600 colors */}, {32, 32, 30, /* 15 bits, 30720 colors */} }; /* * See if there is already an instance for windows using * the same colormap. If so then just re-use it. */ colormap = Tk_Colormap(tkwin); for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { if ((colormap == instancePtr->colormap) && (Tk_Display(tkwin) == instancePtr->display)) { /* * Re-use this instance. */ if (instancePtr->refCount == 0) { /* * We are resurrecting this instance. */ Tcl_CancelIdleCall(DisposeInstance, (ClientData) instancePtr); if (instancePtr->colorTablePtr != NULL) { FreeColorTable(instancePtr->colorTablePtr); } GetColorTable(instancePtr); } instancePtr->refCount++; return (ClientData) instancePtr; } } /* * The image isn't already in use in a window with the same colormap. * Make a new instance of the image. */ instancePtr = (PhotoInstance *) ckalloc(sizeof(PhotoInstance)); instancePtr->masterPtr = masterPtr; instancePtr->display = Tk_Display(tkwin); instancePtr->colormap = Tk_Colormap(tkwin); Tk_PreserveColormap(instancePtr->display, instancePtr->colormap); instancePtr->refCount = 1; instancePtr->colorTablePtr = NULL; instancePtr->pixels = None; instancePtr->error = NULL; instancePtr->width = 0; instancePtr->height = 0; instancePtr->imagePtr = 0; instancePtr->nextPtr = masterPtr->instancePtr; masterPtr->instancePtr = instancePtr; /* * Obtain information about the visual and decide on the * default palette. */ visualInfo.screen = Tk_ScreenNumber(tkwin); visualInfo.visualid = XVisualIDFromVisual(Tk_Visual(tkwin)); visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask | VisualIDMask, &visualInfo, &numVisuals); nRed = 2; nGreen = nBlue = 0; mono = 1; if (visInfoPtr != NULL) { instancePtr->visualInfo = *visInfoPtr; switch (visInfoPtr->class) { case DirectColor: case TrueColor: nRed = 1 << CountBits(visInfoPtr->red_mask); nGreen = 1 << CountBits(visInfoPtr->green_mask); nBlue = 1 << CountBits(visInfoPtr->blue_mask); mono = 0; break; case PseudoColor: case StaticColor: if (visInfoPtr->depth > 15) { nRed = 32; nGreen = 32; nBlue = 32; mono = 0; } else if (visInfoPtr->depth >= 3) { int *ip = paletteChoice[visInfoPtr->depth - 3]; nRed = ip[0]; nGreen = ip[1]; nBlue = ip[2]; mono = 0; } break; case GrayScale: case StaticGray: nRed = 1 << visInfoPtr->depth; break; } XFree((char *) visInfoPtr); } else { panic("ImgPhotoGet couldn't find visual for window"); } sprintf(buf, ((mono) ? "%d": "%d/%d/%d"), nRed, nGreen, nBlue); instancePtr->defaultPalette = Tk_GetUid(buf); /* * Make a GC with background = black and foreground = white. */ white = Tk_GetColor(masterPtr->interp, tkwin, "white"); black = Tk_GetColor(masterPtr->interp, tkwin, "black"); gcValues.foreground = (white != NULL)? white->pixel: WhitePixelOfScreen(Tk_Screen(tkwin)); gcValues.background = (black != NULL)? black->pixel: BlackPixelOfScreen(Tk_Screen(tkwin)); gcValues.graphics_exposures = False; instancePtr->gc = Tk_GetGC(tkwin, GCForeground|GCBackground|GCGraphicsExposures, &gcValues); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -