diff options
Diffstat (limited to 'generic/tkImgPhoto.c')
-rw-r--r-- | generic/tkImgPhoto.c | 3229 |
1 files changed, 1653 insertions, 1576 deletions
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 3f439de..ef907e6 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -1,17 +1,17 @@ /* * tkImgPhoto.c -- * - * Implements images of type "photo" for Tk. Photo images are - * stored in full color (32 bits per pixel including alpha channel) - * and displayed using dithering if necessary. + * Implements images of type "photo" for Tk. Photo images are stored in + * full color (32 bits per pixel including alpha channel) and displayed + * using dithering if necessary. * * Copyright (c) 1994 The Australian National University. * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2002 Donal K. Fellows + * Copyright (c) 2002-2003 Donal K. Fellows * Copyright (c) 2003 ActiveState Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Author: Paul Mackerras (paulus@cs.anu.edu.au), * Department of Computer Science, @@ -19,8 +19,6 @@ */ #include "tkInt.h" -#include "tkPort.h" -#include "tclMath.h" #include <ctype.h> #ifdef __WIN32__ @@ -31,12 +29,12 @@ * Declaration for internal Xlib function used here: */ -extern int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image)); +extern int _XInitImageFuncPtrs(XImage *image); /* - * A signed 8-bit integral type. If chars are unsigned and the compiler - * isn't an ANSI one, then we have to use short instead (which wastes - * space) to get signed behavior. + * A signed 8-bit integral type. If chars are unsigned and the compiler isn't + * an ANSI one, then we have to use short instead (which wastes space) to get + * signed behavior. */ #if defined(__STDC__) || defined(_AIX) @@ -50,16 +48,15 @@ extern int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image)); #endif /* - * An unsigned 32-bit integral type, used for pixel values. - * We use int rather than long here to accommodate those systems - * where longs are 64 bits. + * An unsigned 32-bit integral type, used for pixel values. We use int rather + * than long here to accommodate those systems where longs are 64 bits. */ typedef unsigned int pixel; /* - * The maximum number of pixels to transmit to the server in a - * single XPutImage call. + * The maximum number of pixels to transmit to the server in a single + * XPutImage call. */ #define MAX_PIXELS 65536 @@ -67,20 +64,19 @@ typedef unsigned int pixel; /* * The set of colors required to display a photo image in a window depends on: * - the visual used by the window - * - the palette, which specifies how many levels of each primary - * color to use, and + * - the palette, which specifies how many levels of each primary color to + * use, and * - the gamma value for the image. * - * Pixel values allocated for specific colors are valid only for the - * colormap in which they were allocated. Sets of pixel values - * allocated for displaying photos are re-used in other windows if - * possible, that is, if the display, colormap, palette and gamma - * values match. A hash table is used to locate these sets of pixel - * values, using the following data structure as key: + * Pixel values allocated for specific colors are valid only for the colormap + * in which they were allocated. Sets of pixel values allocated for displaying + * photos are re-used in other windows if possible, that is, if the display, + * colormap, palette and gamma values match. A hash table is used to locate + * these sets of pixel values, using the following data structure as key: */ typedef struct { - Display *display; /* Qualifies the colormap resource ID */ + Display *display; /* Qualifies the colormap resource ID. */ Colormap colormap; /* Colormap that the windows are using. */ double gamma; /* Gamma exponent value for images. */ Tk_Uid palette; /* Specifies how many shades of each primary @@ -88,33 +84,33 @@ typedef struct { } ColorTableId; /* - * For a particular (display, colormap, palette, gamma) combination, - * a data structure of the following type is used to store the allocated - * pixel values and other information: + * For a particular (display, colormap, palette, gamma) combination, a data + * structure of the following type is used to store the allocated pixel values + * and other information: */ typedef struct ColorTable { - ColorTableId id; /* Information used in selecting this - * color table. */ + ColorTableId id; /* Information used in selecting this color + * table. */ int flags; /* See below. */ int refCount; /* Number of instances using this map. */ - int liveRefCount; /* Number of instances which are actually - * in use, using this map. */ + int liveRefCount; /* Number of instances which are actually in + * use, using this map. */ int numColors; /* Number of colors allocated for this map. */ XVisualInfo visualInfo; /* Information about the visual for windows * using this color table. */ - pixel redValues[256]; /* Maps 8-bit values of red intensity - * to a pixel value or index in pixelMap. */ - pixel greenValues[256]; /* Ditto for green intensity */ - pixel blueValues[256]; /* Ditto for blue intensity */ + pixel redValues[256]; /* Maps 8-bit values of red intensity to a + * pixel value or index in pixelMap. */ + pixel greenValues[256]; /* Ditto for green intensity. */ + pixel blueValues[256]; /* Ditto for blue intensity. */ unsigned long *pixelMap; /* Actual pixel values allocated. */ unsigned char colorQuant[3][256]; /* Maps 8-bit intensities to quantized - * intensities. The first index is 0 for - * red, 1 for green, 2 for blue. */ + * intensities. The first index is 0 for red, + * 1 for green, 2 for blue. */ } ColorTable; /* @@ -123,12 +119,13 @@ typedef struct ColorTable { * available. * COLOR_WINDOW: 1 means a full 3-D color cube has been * allocated. - * DISPOSE_PENDING: 1 means a call to DisposeColorTable has - * been scheduled as an idle handler, but it - * hasn't been invoked yet. - * MAP_COLORS: 1 means pixel values should be mapped - * through pixelMap. + * DISPOSE_PENDING: 1 means a call to DisposeColorTable has been + * scheduled as an idle handler, but it hasn't + * been invoked yet. + * MAP_COLORS: 1 means pixel values should be mapped through + * pixelMap. */ + #ifdef COLOR_WINDOW #undef COLOR_WINDOW #endif @@ -143,14 +140,13 @@ typedef struct ColorTable { */ typedef struct PhotoMaster { - Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means - * the image is being deleted. */ - Tcl_Interp *interp; /* Interpreter associated with the - * application using this image. */ - Tcl_Command imageCmd; /* Token for image command (used to delete - * it when the image goes away). NULL means - * the image command has already been - * deleted. */ + Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means the + * image is being deleted. */ + Tcl_Interp *interp; /* Interpreter associated with the application + * using this image. */ + Tcl_Command imageCmd; /* Token for image command (used to delete it + * when the image goes away). NULL means the + * image command has already been deleted. */ int flags; /* Sundry flags, defined below. */ int width, height; /* Dimensions of image. */ int userWidth, userHeight; /* User-declared image dimensions. */ @@ -159,26 +155,27 @@ typedef struct PhotoMaster { double gamma; /* Display gamma value to correct for. */ char *fileString; /* Name of file to read into image. */ Tcl_Obj *dataString; /* Object to use as contents of image. */ - Tcl_Obj *format; /* User-specified format of data in image - * file or string value. */ + Tcl_Obj *format; /* User-specified format of data in image file + * or string value. */ unsigned char *pix32; /* Local storage for 32-bit image. */ - int ditherX, ditherY; /* Location of first incorrectly - * dithered pixel in image. */ - TkRegion validRegion; /* Tk region indicating which parts of - * the image have valid image data. */ + int ditherX, ditherY; /* Location of first incorrectly dithered + * pixel in image. */ + TkRegion validRegion; /* Tk region indicating which parts of the + * image have valid image data. */ struct PhotoInstance *instancePtr; - /* First in the list of instances - * associated with this master. */ + /* First in the list of instances associated + * with this master. */ } PhotoMaster; /* * Bit definitions for the flags field of a PhotoMaster. * COLOR_IMAGE: 1 means that the image has different color * components. - * IMAGE_CHANGED: 1 means that the instances of this image - * need to be redithered. - * COMPLEX_ALPHA: 1 means that the instances of this image - * have alpha values that aren't 0 or 255. + * IMAGE_CHANGED: 1 means that the instances of this image need + * to be redithered. + * COMPLEX_ALPHA: 1 means that the instances of this image have + * alpha values that aren't 0 or 255, and so need + * the copy-merge-replace renderer . */ #define COLOR_IMAGE 1 @@ -193,9 +190,8 @@ typedef struct PhotoMaster { #define SOURCE_IS_SIMPLE_ALPHA_PHOTO 0x10000000 /* - * The following data structure represents all of the instances of - * a photo image in windows on a given screen that are using the - * same colormap. + * The following data structure represents all of the instances of a photo + * image in windows on a given screen that are using the same colormap. */ typedef struct PhotoInstance { @@ -204,34 +200,34 @@ typedef struct PhotoInstance { Colormap colormap; /* The image may only be used in windows with * this particular colormap. */ struct PhotoInstance *nextPtr; - /* Pointer to the next instance in the list - * of instances associated with this master. */ + /* Pointer to the next instance in the list of + * instances associated with this master. */ int refCount; /* Number of instances using this structure. */ Tk_Uid palette; /* Palette for these particular instances. */ double gamma; /* Gamma value for these instances. */ - Tk_Uid defaultPalette; /* Default palette to use if a palette - * is not specified for the master. */ + Tk_Uid defaultPalette; /* Default palette to use if a palette is not + * specified for the master. */ ColorTable *colorTablePtr; /* Pointer to information about colors - * allocated for image display in windows - * like this one. */ + * allocated for image display in windows like + * this one. */ Pixmap pixels; /* X pixmap containing dithered image. */ int width, height; /* Dimensions of the pixmap. */ schar *error; /* Error image, used in dithering. */ XImage *imagePtr; /* Image structure for converted pixels. */ XVisualInfo visualInfo; /* Information about the visual that these * windows are using. */ - GC gc; /* Graphics context for writing images - * to the pixmap. */ + GC gc; /* Graphics context for writing images to the + * pixmap. */ } PhotoInstance; /* - * The following data structure is used to return information - * from ParseSubcommandOptions: + * The following data structure is used to return information from + * ParseSubcommandOptions: */ struct SubcommandOptions { - int options; /* Individual bits indicate which - * options were specified - see below. */ + int options; /* Individual bits indicate which options were + * specified - see below. */ Tcl_Obj *name; /* Name specified without an option. */ int fromX, fromY; /* Values specified for -from option. */ int fromX2, fromY2; /* Second coordinate pair for -from option. */ @@ -241,15 +237,16 @@ struct SubcommandOptions { int subsampleX, subsampleY; /* Values specified for -subsample option. */ Tcl_Obj *format; /* Value specified for -format option. */ XColor *background; /* Value specified for -background option. */ - int compositingRule; /* Value specified for -compositingrule opt */ + int compositingRule; /* Value specified for -compositingrule + * option. */ }; /* - * Bit definitions for use with ParseSubcommandOptions: - * Each bit is set in the allowedOptions parameter on a call to - * ParseSubcommandOptions if that option is allowed for the current - * photo image subcommand. On return, the bit is set in the options - * field of the SubcommandOptions structure if that option was specified. + * Bit definitions for use with ParseSubcommandOptions: each bit is set in the + * allowedOptions parameter on a call to ParseSubcommandOptions if that option + * is allowed for the current photo image subcommand. On return, the bit is + * set in the options field of the SubcommandOptions structure if that option + * was specified. * * OPT_BACKGROUND: Set if -format option allowed/specified. * OPT_COMPOSITE: Set if -compositingrule option allowed/spec'd. @@ -273,8 +270,8 @@ struct SubcommandOptions { #define OPT_ZOOM 0x100 /* - * List of option names. The order here must match the order of - * declarations of the OPT_* constants above. + * List of option names. The order here must match the order of declarations + * of the OPT_* constants above. */ static char *optionNames[] = { @@ -287,13 +284,14 @@ static char *optionNames[] = { "-subsample", "-to", "-zoom", - (char *) NULL + NULL }; /* - * Message to generate when an attempt to resize an image fails due - * to memory problems. + * Message to generate when an attempt to resize an image fails due to memory + * problems. */ + #define TK_PHOTO_ALLOC_FAILURE_MESSAGE \ "not enough free memory for image buffer" @@ -301,23 +299,21 @@ static char *optionNames[] = { * Functions used in the type record for photo images. */ -static int ImgPhotoCreate _ANSI_ARGS_((Tcl_Interp *interp, - char *name, int objc, Tcl_Obj *CONST objv[], +static int ImgPhotoCreate(Tcl_Interp *interp, char *name, + int objc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr, Tk_ImageMaster master, - ClientData *clientDataPtr)); -static ClientData ImgPhotoGet _ANSI_ARGS_((Tk_Window tkwin, - ClientData clientData)); -static void ImgPhotoDisplay _ANSI_ARGS_((ClientData clientData, + ClientData *clientDataPtr); +static ClientData ImgPhotoGet(Tk_Window tkwin, ClientData clientData); +static void ImgPhotoDisplay(ClientData clientData, Display *display, Drawable drawable, int imageX, int imageY, int width, int height, - int drawableX, int drawableY)); -static void ImgPhotoFree _ANSI_ARGS_((ClientData clientData, - Display *display)); -static void ImgPhotoDelete _ANSI_ARGS_((ClientData clientData)); -static int ImgPhotoPostscript _ANSI_ARGS_((ClientData clientData, + int drawableX, int drawableY); +static void ImgPhotoFree(ClientData clientData, Display *display); +static void ImgPhotoDelete(ClientData clientData); +static int ImgPhotoPostscript(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, int x, int y, int width, - int height, int prepass)); + int height, int prepass); /* * The type record itself for photo images: @@ -331,15 +327,18 @@ Tk_ImageType tkPhotoImageType = { ImgPhotoFree, /* freeProc */ ImgPhotoDelete, /* deleteProc */ ImgPhotoPostscript, /* postscriptProc */ - (Tk_ImageType *) NULL /* nextPtr */ + NULL /* nextPtr */ }; typedef struct ThreadSpecificData { - Tk_PhotoImageFormat *formatList; /* Pointer to the first in the - * list of known photo image formats.*/ - Tk_PhotoImageFormat *oldFormatList; /* Pointer to the first in the - * list of known photo image formats.*/ - int initialized; /* set to 1 if we've initialized the strucuture */ + Tk_PhotoImageFormat *formatList; + /* Pointer to the first in the list of known + * photo image formats.*/ + Tk_PhotoImageFormat *oldFormatList; + /* Pointer to the first in the list of known + * photo image formats.*/ + int initialized; /* Set to 1 if we've initialized the + * strucuture. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -355,24 +354,24 @@ static Tcl_ThreadDataKey dataKey; /* * Information used for parsing configuration specifications: */ + static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_DOUBLE, "-gamma", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-file", NULL, NULL, + NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_DOUBLE, "-gamma", NULL, NULL, DEF_PHOTO_GAMMA, Tk_Offset(PhotoMaster, gamma), 0}, - {TK_CONFIG_INT, "-height", (char *) NULL, (char *) NULL, + {TK_CONFIG_INT, "-height", NULL, NULL, DEF_PHOTO_HEIGHT, Tk_Offset(PhotoMaster, userHeight), 0}, - {TK_CONFIG_UID, "-palette", (char *) NULL, (char *) NULL, + {TK_CONFIG_UID, "-palette", NULL, NULL, DEF_PHOTO_PALETTE, Tk_Offset(PhotoMaster, palette), 0}, - {TK_CONFIG_INT, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_INT, "-width", NULL, NULL, DEF_PHOTO_WIDTH, Tk_Offset(PhotoMaster, userWidth), 0}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Hash table used to hash from (display, colormap, palette, gamma) - * to ColorTable address. + * Hash table used to hash from (display, colormap, palette, gamma) to + * ColorTable address. */ static Tcl_HashTable imgPhotoColorHash; @@ -392,61 +391,53 @@ static int imgPhotoColorHashInitialized; * Forward declarations */ -static void PhotoFormatThreadExitProc _ANSI_ARGS_(( - ClientData clientData)); -static int ImgPhotoCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int ParseSubcommandOptions _ANSI_ARGS_(( +static void PhotoFormatThreadExitProc(ClientData clientData); +static int ImgPhotoCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int ParseSubcommandOptions( struct SubcommandOptions *optPtr, Tcl_Interp *interp, int allowedOptions, - int *indexPtr, int objc, Tcl_Obj *CONST objv[])); -static void ImgPhotoCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static int ImgPhotoConfigureMaster _ANSI_ARGS_(( - Tcl_Interp *interp, PhotoMaster *masterPtr, - int objc, Tcl_Obj *CONST objv[], int flags)); -static void ImgPhotoConfigureInstance _ANSI_ARGS_(( - PhotoInstance *instancePtr)); -static int ToggleComplexAlphaIfNeeded _ANSI_ARGS_(( - PhotoMaster *mPtr)); -static void ImgPhotoBlendComplexAlpha _ANSI_ARGS_(( - XImage *bgImg, PhotoInstance *iPtr, - int xOffset, int yOffset, int width, int height)); -static int ImgPhotoSetSize _ANSI_ARGS_((PhotoMaster *masterPtr, - int width, int height)); -static void ImgPhotoInstanceSetSize _ANSI_ARGS_(( - PhotoInstance *instancePtr)); -static int ImgStringWrite _ANSI_ARGS_((Tcl_Interp *interp, + int *indexPtr, int objc, Tcl_Obj *const objv[]); +static void ImgPhotoCmdDeletedProc(ClientData clientData); +static int ImgPhotoConfigureMaster(Tcl_Interp *interp, + PhotoMaster *masterPtr, int objc, + Tcl_Obj *const objv[], int flags); +static void ImgPhotoConfigureInstance(PhotoInstance *instancePtr); +static int ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr); +static void ImgPhotoBlendComplexAlpha(XImage *bgImg, + PhotoInstance *iPtr, int xOffset, int yOffset, + int width, int height); +static int ImgPhotoSetSize(PhotoMaster *masterPtr, int width, + int height); +static void ImgPhotoInstanceSetSize(PhotoInstance *instancePtr); +static int ImgStringWrite(Tcl_Interp *interp, Tcl_Obj *formatString, - Tk_PhotoImageBlock *blockPtr)); -static char * ImgGetPhoto _ANSI_ARGS_((PhotoMaster *masterPtr, + Tk_PhotoImageBlock *blockPtr); +static char * ImgGetPhoto(PhotoMaster *masterPtr, Tk_PhotoImageBlock *blockPtr, - struct SubcommandOptions *optPtr)); -static int IsValidPalette _ANSI_ARGS_((PhotoInstance *instancePtr, - CONST char *palette)); -static int CountBits _ANSI_ARGS_((pixel mask)); -static void GetColorTable _ANSI_ARGS_((PhotoInstance *instancePtr)); -static void FreeColorTable _ANSI_ARGS_((ColorTable *colorPtr, - int force)); -static void AllocateColors _ANSI_ARGS_((ColorTable *colorPtr)); -static void DisposeColorTable _ANSI_ARGS_((ClientData clientData)); -static void DisposeInstance _ANSI_ARGS_((ClientData clientData)); -static int ReclaimColors _ANSI_ARGS_((ColorTableId *id, - int numColors)); -static int MatchFileFormat _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan, char *fileName, Tcl_Obj *formatString, + struct SubcommandOptions *optPtr); +static int IsValidPalette(PhotoInstance *instancePtr, + const char *palette); +static int CountBits(pixel mask); +static void GetColorTable(PhotoInstance *instancePtr); +static void FreeColorTable(ColorTable *colorPtr, int force); +static void AllocateColors(ColorTable *colorPtr); +static void DisposeColorTable(ClientData clientData); +static void DisposeInstance(ClientData clientData); +static int ReclaimColors(ColorTableId *id, int numColors); +static int MatchFileFormat(Tcl_Interp *interp, Tcl_Channel chan, + char *fileName, Tcl_Obj *formatString, Tk_PhotoImageFormat **imageFormatPtr, - int *widthPtr, int *heightPtr, int *oldformat)); -static int MatchStringFormat _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *data, Tcl_Obj *formatString, + int *widthPtr, int *heightPtr, int *oldformat); +static int MatchStringFormat(Tcl_Interp *interp, Tcl_Obj *data, + Tcl_Obj *formatString, Tk_PhotoImageFormat **imageFormatPtr, - int *widthPtr, int *heightPtr, int *oldformat)); -static Tcl_ObjCmdProc * PhotoOptionFind _ANSI_ARGS_((Tcl_Interp * interp, - Tcl_Obj *obj)); -static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr, - int x, int y, int width, int height)); -static void PhotoOptionCleanupProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp)); + int *widthPtr, int *heightPtr, int *oldformat); +static Tcl_ObjCmdProc * PhotoOptionFind(Tcl_Interp *interp, Tcl_Obj *obj); +static void DitherInstance(PhotoInstance *instancePtr, int x, + int y, int width, int height); +static void PhotoOptionCleanupProc(ClientData clientData, + Tcl_Interp *interp); #undef MIN #define MIN(a, b) ((a) < (b)? (a): (b)) @@ -456,35 +447,30 @@ static void PhotoOptionCleanupProc _ANSI_ARGS_(( /* *---------------------------------------------------------------------- * - * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat -- + * PhotoFormatThreadExitProc -- * - * This procedure is invoked by an image file handler to register - * a new photo image format and the procedures that handle the - * new format. The procedure is typically invoked during - * Tcl_AppInit. + * Clean up the registered list of photo formats. * * Results: * None. * * Side effects: - * The new image file format is entered into a table used in the - * photo image "read" and "write" subcommands. + * The thread's linked lists of photo image formats is deleted. * *---------------------------------------------------------------------- */ static void -PhotoFormatThreadExitProc(clientData) - ClientData clientData; /* not used */ +PhotoFormatThreadExitProc( + ClientData clientData) /* not used */ { Tk_PhotoImageFormat *freePtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); while (tsdPtr->oldFormatList != NULL) { freePtr = tsdPtr->oldFormatList; tsdPtr->oldFormatList = tsdPtr->oldFormatList->nextPtr; - ckfree((char *) freePtr->name); ckfree((char *) freePtr); } while (tsdPtr->formatList != NULL) { @@ -500,31 +486,30 @@ PhotoFormatThreadExitProc(clientData) * * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat -- * - * This procedure is invoked by an image file handler to register - * a new photo image format and the procedures that handle the - * new format. The procedure is typically invoked during - * Tcl_AppInit. + * This function is invoked by an image file handler to register a new + * photo image format and the functions that handle the new format. The + * function is typically invoked during Tcl_AppInit. * * Results: * None. * * Side effects: - * The new image file format is entered into a table used in the - * photo image "read" and "write" subcommands. + * The new image file format is entered into a table used in the photo + * image "read" and "write" subcommands. * *---------------------------------------------------------------------- */ + void -Tk_CreateOldPhotoImageFormat(formatPtr) - Tk_PhotoImageFormat *formatPtr; - /* Structure describing the format. All of - * the fields except "nextPtr" must be filled - * in by caller. Must not have been passed - * to Tk_CreatePhotoImageFormat previously. */ +Tk_CreateOldPhotoImageFormat( + Tk_PhotoImageFormat *formatPtr) + /* Structure describing the format. All of the + * fields except "nextPtr" must be filled in + * by caller. */ { Tk_PhotoImageFormat *copyPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!tsdPtr->initialized) { tsdPtr->initialized = 1; @@ -532,23 +517,20 @@ Tk_CreateOldPhotoImageFormat(formatPtr) } copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat)); *copyPtr = *formatPtr; - copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1)); - strcpy(copyPtr->name, formatPtr->name); copyPtr->nextPtr = tsdPtr->oldFormatList; tsdPtr->oldFormatList = copyPtr; } void -Tk_CreatePhotoImageFormat(formatPtr) - Tk_PhotoImageFormat *formatPtr; - /* Structure describing the format. All of - * the fields except "nextPtr" must be filled - * in by caller. Must not have been passed - * to Tk_CreatePhotoImageFormat previously. */ +Tk_CreatePhotoImageFormat( + Tk_PhotoImageFormat *formatPtr) + /* Structure describing the format. All of the + * fields except "nextPtr" must be filled in + * by caller. */ { Tk_PhotoImageFormat *copyPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!tsdPtr->initialized) { tsdPtr->initialized = 1; @@ -556,12 +538,14 @@ Tk_CreatePhotoImageFormat(formatPtr) } copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat)); *copyPtr = *formatPtr; - copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1)); - strcpy(copyPtr->name, formatPtr->name); if (isupper((unsigned char) *formatPtr->name)) { copyPtr->nextPtr = tsdPtr->oldFormatList; tsdPtr->oldFormatList = copyPtr; } else { + /* for compatibility with aMSN: make a copy of formatPtr->name */ + char *name = ckalloc(strlen(formatPtr->name) + 1); + strcpy(name, formatPtr->name); + copyPtr->name = name; copyPtr->nextPtr = tsdPtr->formatList; tsdPtr->formatList = copyPtr; } @@ -572,32 +556,31 @@ Tk_CreatePhotoImageFormat(formatPtr) * * ImgPhotoCreate -- * - * This procedure is called by the Tk image code to create - * a new photo image. + * This function is called by the Tk image code to create a new photo + * image. * * Results: * A standard Tcl result. * * Side effects: - * The data structure for a new photo image is allocated and - * initialized. + * The data structure for a new photo image is allocated and initialized. * *---------------------------------------------------------------------- */ static int -ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) - Tcl_Interp *interp; /* Interpreter for application containing +ImgPhotoCreate( + Tcl_Interp *interp, /* Interpreter for application containing * image. */ - char *name; /* Name to use for image. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects for options (doesn't + char *name, /* Name to use for image. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[], /* Argument objects for options (doesn't * include image name or type). */ - Tk_ImageType *typePtr; /* Pointer to our type record (not used). */ - Tk_ImageMaster master; /* Token for image, to be used by us in - * later callbacks. */ - ClientData *clientDataPtr; /* Store manager's token for image here; - * it will be returned in later callbacks. */ + Tk_ImageType *typePtr, /* Pointer to our type record (not used). */ + Tk_ImageMaster master, /* Token for image, to be used by us in later + * callbacks. */ + ClientData *clientDataPtr) /* Store manager's token for image here; it + * will be returned in later callbacks. */ { PhotoMaster *masterPtr; @@ -606,7 +589,7 @@ ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) */ masterPtr = (PhotoMaster *) ckalloc(sizeof(PhotoMaster)); - memset((void *) masterPtr, 0, sizeof(PhotoMaster)); + memset(masterPtr, 0, sizeof(PhotoMaster)); masterPtr->tkMaster = master; masterPtr->interp = interp; masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd, @@ -634,9 +617,9 @@ ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) * * ImgPhotoCmd -- * - * This procedure is invoked to process the Tcl command that - * corresponds to a photo image. See the user documentation - * for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a photo image. See the user documentation for details on what it + * does. * * Results: * A standard Tcl result. @@ -648,42 +631,35 @@ ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) */ static int -ImgPhotoCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about photo master. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +ImgPhotoCmd( + ClientData clientData, /* Information about photo master. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - int oldformat = 0; - static CONST char *photoOptions[] = { + static const char *photoOptions[] = { "blank", "cget", "configure", "copy", "data", "get", "put", - "read", "redither", "transparency", "write", (char *) NULL + "read", "redither", "transparency", "write", NULL }; - enum options { + enum PhotoOptions { PHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA, PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_TRANS, PHOTO_WRITE }; PhotoMaster *masterPtr = (PhotoMaster *) clientData; - int result, index; - int x, y, width, height; - int dataWidth, dataHeight; + int result, index, x, y, width, height, dataWidth, dataHeight, listObjc; struct SubcommandOptions options; - int listArgc; - CONST char **listArgv; - CONST char **srcArgv; + Tcl_Obj **listObjv, **srcObjv; unsigned char *pixelPtr; Tk_PhotoImageBlock block; Tk_Window tkwin; - XColor color; Tk_PhotoImageFormat *imageFormat; - int imageWidth, imageHeight; - int length, matched; + int imageWidth, imageHeight, matched, length, oldformat = 0; Tcl_Channel chan; Tk_PhotoHandle srcHandle; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); @@ -694,13 +670,13 @@ ImgPhotoCmd(clientData, interp, objc, objv) &index) != TCL_OK) { Tcl_ObjCmdProc *proc; proc = PhotoOptionFind(interp, objv[1]); - if (proc == (Tcl_ObjCmdProc *) NULL) { + if (proc == NULL) { return TCL_ERROR; } return proc(clientData, interp, objc, objv); } - switch ((enum options) index) { + switch ((enum PhotoOptions) index) { case PHOTO_BLANK: /* * photo blank command - just call Tk_PhotoBlank. @@ -710,7 +686,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) Tk_PhotoBlank(masterPtr); return TCL_OK; } else { - Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); + Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } @@ -744,53 +720,51 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (objc == 2) { Tcl_Obj *obj, *subobj; + result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), - configSpecs, (char *) masterPtr, (char *) NULL, 0); + configSpecs, (char *) masterPtr, NULL, 0); if (result != TCL_OK) { return result; } obj = Tcl_NewObj(); subobj = Tcl_NewStringObj("-data {} {} {}", 14); if (masterPtr->dataString) { - Tcl_ListObjAppendElement(interp, subobj, masterPtr->dataString); + Tcl_ListObjAppendElement(NULL, subobj, masterPtr->dataString); } else { - Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL); + Tcl_AppendStringsToObj(subobj, " {}", NULL); } Tcl_ListObjAppendElement(interp, obj, subobj); subobj = Tcl_NewStringObj("-format {} {} {}", 16); if (masterPtr->format) { - Tcl_ListObjAppendElement(interp, subobj, masterPtr->format); + Tcl_ListObjAppendElement(NULL, subobj, masterPtr->format); } else { - Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL); + Tcl_AppendStringsToObj(subobj, " {}", NULL); } Tcl_ListObjAppendElement(interp, obj, subobj); Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp)); Tcl_SetObjResult(interp, obj); return TCL_OK; - } - if (objc == 3) { + + } else if (objc == 3) { char *arg = Tcl_GetStringFromObj(objv[2], &length); - if (!strncmp(arg, "-data", (unsigned) length)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "-data {} {} {}", (char *) NULL); + if (length > 1 && !strncmp(arg, "-data", (unsigned) length)) { + Tcl_AppendResult(interp, "-data {} {} {}", NULL); if (masterPtr->dataString) { Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), masterPtr->dataString); } else { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - " {}", (char *) NULL); + Tcl_AppendResult(interp, " {}", NULL); } return TCL_OK; - } else if (!strncmp(arg, "-format", (unsigned) length)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "-format {} {} {}", (char *) NULL); + } else if (length > 1 && + !strncmp(arg, "-format", (unsigned) length)) { + Tcl_AppendResult(interp, "-format {} {} {}", NULL); if (masterPtr->format) { Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), masterPtr->format); } else { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - " {}", (char *) NULL); + Tcl_AppendResult(interp, " {}", NULL); } return TCL_OK; } else { @@ -807,7 +781,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.zoomX = options.zoomY = 1; options.subsampleX = options.subsampleY = 1; options.name = NULL; @@ -832,7 +806,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (srcHandle == NULL) { Tcl_AppendResult(interp, "image \"", Tcl_GetString(options.name), "\" doesn't", - " exist or is not a photo image", (char *) NULL); + " exist or is not a photo image", NULL); return TCL_ERROR; } Tk_PhotoGetImage(srcHandle, &block); @@ -840,7 +814,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) || (options.fromX2 > block.width) || (options.fromY2 > block.height)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", - "outside source image", (char *) NULL); + "outside source image", NULL); return TCL_ERROR; } @@ -893,8 +867,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (ImgPhotoSetSize(masterPtr, options.toX2, options.toY2) != TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); return TCL_ERROR; } } @@ -907,12 +880,11 @@ ImgPhotoCmd(clientData, interp, objc, objv) + options.fromY * block.pitch; block.width = options.fromX2 - options.fromX; block.height = options.fromY2 - options.fromY; - Tk_PhotoPutZoomedBlock((Tk_PhotoHandle) masterPtr, &block, - options.toX, options.toY, options.toX2 - options.toX, + return Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) masterPtr, + &block, options.toX, options.toY, options.toX2 - options.toX, options.toY2 - options.toY, options.zoomX, options.zoomY, options.subsampleX, options.subsampleY, options.compositingRule); - return TCL_OK; case PHOTO_DATA: { char *data; @@ -920,10 +892,11 @@ ImgPhotoCmd(clientData, interp, objc, objv) /* * photo data command - first parse and check any options given. */ + Tk_ImageStringWriteProc *stringWriteProc = NULL; index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; options.fromX = 0; @@ -942,7 +915,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) || (options.fromX2 > masterPtr->width) || (options.fromY2 > masterPtr->height)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", - "outside image", (char *) NULL); + "outside image", NULL); return TCL_ERROR; } @@ -990,8 +963,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (stringWriteProc == NULL) { Tcl_AppendResult(interp, "image string format \"", Tcl_GetString(options.format), "\" is ", - (matched ? "not supported" : "unknown"), - (char *) NULL); + (matched ? "not supported" : "unknown"), NULL); return TCL_ERROR; } } else { @@ -999,8 +971,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) } /* - * Call the handler's string write procedure to write out - * the image. + * Call the handler's string write function to write out the image. */ data = ImgGetPhoto(masterPtr, &block, &options); @@ -1009,9 +980,9 @@ ImgPhotoCmd(clientData, interp, objc, objv) Tcl_DString buffer; Tcl_DStringInit(&buffer); - result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_DString *buffer, char *formatString, - Tk_PhotoImageBlock *blockPtr))) stringWriteProc) + result = ((int (*) (Tcl_Interp *interp, + Tcl_DString *dataPtr, char *formatString, + Tk_PhotoImageBlock *blockPtr)) stringWriteProc) (interp, &buffer, Tcl_GetString(options.format), &block); if (result == TCL_OK) { Tcl_DStringResult(interp, &buffer); @@ -1019,10 +990,11 @@ ImgPhotoCmd(clientData, interp, objc, objv) Tcl_DStringFree(&buffer); } } else { - result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp, + + result = ((int (*) (Tcl_Interp *interp, Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr, - VOID *dummy))) stringWriteProc) - (interp, options.format, &block, (VOID *) NULL); + void *dummy)) stringWriteProc) + (interp, options.format, &block, NULL); } if (options.background) { Tk_FreeColor(options.background); @@ -1051,7 +1023,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " get: ", - "coordinates out of range", (char *) NULL); + "coordinates out of range", NULL); return TCL_ERROR; } @@ -1062,7 +1034,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; sprintf(string, "%d %d %d", pixelPtr[0], pixelPtr[1], pixelPtr[2]); - Tcl_AppendResult(interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, NULL); return TCL_OK; } @@ -1072,7 +1044,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT, &index, objc, objv) != TCL_OK) { @@ -1083,7 +1055,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) return TCL_ERROR; } - if (MatchStringFormat(interp, options.name ? objv[2]:NULL, + if (MatchStringFormat(interp, options.name ? objv[2]:NULL, options.format, &imageFormat, &imageWidth, &imageHeight, &oldformat) == TCL_OK) { Tcl_Obj *format, *data; @@ -1119,8 +1091,8 @@ ImgPhotoCmd(clientData, interp, objc, objv) return TCL_ERROR; } Tcl_ResetResult(interp); - if (Tcl_SplitList(interp, Tcl_GetString(options.name), - &dataHeight, &srcArgv) != TCL_OK) { + if (Tcl_ListObjGetElements(interp, options.name, + &dataHeight, &srcObjv) != TCL_OK) { return TCL_ERROR; } tkwin = Tk_MainWindow(interp); @@ -1128,44 +1100,80 @@ ImgPhotoCmd(clientData, interp, objc, objv) dataWidth = 0; pixelPtr = NULL; for (y = 0; y < dataHeight; ++y) { - if (Tcl_SplitList(interp, srcArgv[y], &listArgc, &listArgv) - != TCL_OK) { + if (Tcl_ListObjGetElements(interp, srcObjv[y], + &listObjc, &listObjv) != TCL_OK) { break; } + if (y == 0) { - if (listArgc == 0) { + if (listObjc == 0) { /* * Lines must be non-empty... */ + break; } - dataWidth = listArgc; + dataWidth = listObjc; pixelPtr = (unsigned char *) ckalloc((unsigned) dataWidth * dataHeight * 3); block.pixelPtr = pixelPtr; - } else if (listArgc != dataWidth) { + } else if (listObjc != dataWidth) { Tcl_AppendResult(interp, "all elements of color list must", - " have the same number of elements", (char *) NULL); - ckfree((char *) listArgv); + " have the same number of elements", NULL); break; } + for (x = 0; x < dataWidth; ++x) { + char *colorString = Tcl_GetString(listObjv[x]); + XColor color; + int tmpr, tmpg, tmpb; + + /* + * We do not use Tk_GetColorFromObj() because we absolutely do + * not want to invoke the fallback code. + */ + + if (colorString[0] == '#') { + if (isxdigit(UCHAR(colorString[1])) && + isxdigit(UCHAR(colorString[2])) && + isxdigit(UCHAR(colorString[3]))) { + if (colorString[4] == '\0') { + /* Got #rgb */ + sscanf(colorString+1, "%1x%1x%1x", + &tmpr, &tmpg, &tmpb); + *pixelPtr++ = tmpr * 0x11; + *pixelPtr++ = tmpg * 0x11; + *pixelPtr++ = tmpb * 0x11; + continue; + } else if (isxdigit(UCHAR(colorString[4])) && + isxdigit(UCHAR(colorString[5])) && + isxdigit(UCHAR(colorString[6])) && + colorString[7] == '\0') { + /* Got #rrggbb */ + sscanf(colorString+1, "%2x%2x%2x", + &tmpr, &tmpg, &tmpb); + *pixelPtr++ = tmpr; + *pixelPtr++ = tmpg; + *pixelPtr++ = tmpb; + continue; + } + } + } + if (!XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), - listArgv[x], &color)) { + colorString, &color)) { Tcl_AppendResult(interp, "can't parse color \"", - listArgv[x], "\"", (char *) NULL); + colorString, "\"", NULL); break; } *pixelPtr++ = color.red >> 8; *pixelPtr++ = color.green >> 8; *pixelPtr++ = color.blue >> 8; } - ckfree((char *) listArgv); if (x < dataWidth) { break; } } - ckfree((char *) srcArgv); if (y < dataHeight || dataHeight == 0 || dataWidth == 0) { if (block.pixelPtr != NULL) { ckfree((char *) block.pixelPtr); @@ -1177,8 +1185,8 @@ ImgPhotoCmd(clientData, interp, objc, objv) } /* - * Fill in default values for the -to option, then - * copy the block in using Tk_PhotoPutBlock. + * Fill in default values for the -to option, then copy the block in + * using Tk_PhotoPutBlock. */ if (!(options.options & OPT_TO) || (options.toX2 < 0)) { @@ -1193,11 +1201,12 @@ ImgPhotoCmd(clientData, interp, objc, objv) block.offset[1] = 1; block.offset[2] = 2; block.offset[3] = 0; - Tk_PhotoPutBlock((ClientData)masterPtr, &block, + result = Tk_PhotoPutBlock(interp, (ClientData)masterPtr, &block, options.toX, options.toY, options.toX2 - options.toX, - options.toY2 - options.toY, TK_PHOTO_COMPOSITE_SET); + options.toY2 - options.toY, + TK_PHOTO_COMPOSITE_SET); ckfree((char *) block.pixelPtr); - return TCL_OK; + return result; case PHOTO_READ: { Tcl_Obj *format; @@ -1207,7 +1216,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; if (ParseSubcommandOptions(&options, interp, @@ -1220,16 +1229,16 @@ ImgPhotoCmd(clientData, interp, objc, objv) return TCL_ERROR; } - /* - * Prevent file system access in safe interpreters. - */ + /* + * Prevent file system access in safe interpreters. + */ + + if (Tcl_IsSafe(interp)) { + Tcl_AppendResult(interp, "can't get image from a file in a", + " safe interpreter", NULL); + return TCL_ERROR; + } - if (Tcl_IsSafe(interp)) { - Tcl_AppendResult(interp, "can't get image from a file in a", - " safe interpreter", (char *) NULL); - return TCL_ERROR; - } - /* * Open the image file and look for a handler for it. */ @@ -1239,17 +1248,17 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (chan == NULL) { return TCL_ERROR; } - if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") + if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) { Tcl_Close(NULL, chan); - return TCL_ERROR; - } - if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary") + return TCL_ERROR; + } + if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary") != TCL_OK) { Tcl_Close(NULL, chan); - return TCL_ERROR; - } - + return TCL_ERROR; + } + if (MatchFileFormat(interp, chan, Tcl_GetString(options.name), options.format, &imageFormat, &imageWidth, &imageHeight, &oldformat) != TCL_OK) { @@ -1265,7 +1274,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) || (options.fromX2 > imageWidth) || (options.fromY2 > imageHeight)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", - "outside source image", (char *) NULL); + "outside source image", NULL); Tcl_Close(NULL, chan); return TCL_ERROR; } @@ -1285,15 +1294,14 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (ImgPhotoSetSize(masterPtr, options.toX + width, options.toY + height) != TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); return TCL_ERROR; } } /* - * Call the handler's file read procedure to read the data - * into the image. + * Call the handler's file read function to read the data into the + * image. */ format = options.format; @@ -1312,13 +1320,13 @@ ImgPhotoCmd(clientData, interp, objc, objv) case PHOTO_REDITHER: if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); + Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } /* - * Call Dither if any part of the image is not correctly - * dithered at present. + * Call Dither if any part of the image is not correctly dithered at + * present. */ x = masterPtr->ditherX; @@ -1346,8 +1354,8 @@ ImgPhotoCmd(clientData, interp, objc, objv) return TCL_OK; case PHOTO_TRANS: { - static CONST char *photoTransOptions[] = { - "get", "set", (char *) NULL + static const char *photoTransOptions[] = { + "get", "set", NULL }; enum transOptions { PHOTO_TRANS_GET, PHOTO_TRANS_SET @@ -1378,8 +1386,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_AppendResult(interp, Tcl_GetString(objv[0]), - " transparency get: coordinates out of range", - (char *) NULL); + " transparency get: coordinates out of range", NULL); return TCL_ERROR; } @@ -1416,8 +1423,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_AppendResult(interp, Tcl_GetString(objv[0]), - " transparency set: coordinates out of range", - (char *) NULL); + " transparency set: coordinates out of range", NULL); return TCL_ERROR; } @@ -1431,20 +1437,24 @@ ImgPhotoCmd(clientData, interp, objc, objv) /* * Make pixel transparent. */ + TkRegion clearRegion = TkCreateRegion(); TkUnionRectWithRegion(&setBox, clearRegion, clearRegion); TkSubtractRegion(masterPtr->validRegion, clearRegion, masterPtr->validRegion); TkDestroyRegion(clearRegion); + /* * Set the alpha value correctly. */ + pixelPtr[3] = 0; } else { /* * Make pixel opaque. */ + TkUnionRectWithRegion(&setBox, masterPtr->validRegion, masterPtr->validRegion); pixelPtr[3] = 255; @@ -1460,31 +1470,31 @@ ImgPhotoCmd(clientData, interp, objc, objv) masterPtr->flags &= ~IMAGE_CHANGED; return TCL_OK; } - } - panic("unexpected fallthrough"); + } + Tcl_Panic("unexpected fallthrough"); } case PHOTO_WRITE: { char *data; Tcl_Obj *format; - /* - * Prevent file system access in safe interpreters. - */ + /* + * Prevent file system access in safe interpreters. + */ + + if (Tcl_IsSafe(interp)) { + Tcl_AppendResult(interp, "can't write image to a file in a", + " safe interpreter", NULL); + return TCL_ERROR; + } - if (Tcl_IsSafe(interp)) { - Tcl_AppendResult(interp, "can't write image to a file in a", - " safe interpreter", (char *) NULL); - return TCL_ERROR; - } - /* * photo write command - first parse and check any options given. */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; if (ParseSubcommandOptions(&options, interp, @@ -1501,7 +1511,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) || (options.fromX2 > masterPtr->width) || (options.fromY2 > masterPtr->height)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", - "outside image", (char *) NULL); + "outside image", NULL); return TCL_ERROR; } @@ -1515,8 +1525,8 @@ ImgPhotoCmd(clientData, interp, objc, objv) } /* - * Search for an appropriate image file format handler, - * and give an error if none is found. + * Search for an appropriate image file format handler, and give an + * error if none is found. */ matched = 0; @@ -1548,23 +1558,21 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (imageFormat == NULL) { if (options.format == NULL) { Tcl_AppendResult(interp, "no available image file format ", - "has file writing capability", (char *) NULL); + "has file writing capability", NULL); } else if (!matched) { Tcl_AppendResult(interp, "image file format \"", Tcl_GetString(options.format), - "\" is unknown", (char *) NULL); + "\" is unknown", NULL); } else { Tcl_AppendResult(interp, "image file format \"", Tcl_GetString(options.format), - "\" has no file writing capability", - (char *) NULL); + "\" has no file writing capability", NULL); } return TCL_ERROR; } /* - * Call the handler's file write procedure to write out - * the image. + * Call the handler's file write function to write out the image. */ data = ImgGetPhoto(masterPtr, &block, &options); @@ -1584,7 +1592,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) } } - panic("unexpected fallthrough"); + Tcl_Panic("unexpected fallthrough"); return TCL_ERROR; /* NOT REACHED */ } @@ -1593,10 +1601,9 @@ ImgPhotoCmd(clientData, interp, objc, objv) * * ParseSubcommandOptions -- * - * This procedure is invoked to process one of the options - * which may be specified for the photo image subcommands, - * namely, -from, -to, -zoom, -subsample, -format, -shrink, - * and -compositingrule. + * This function is invoked to process one of the options which may be + * specified for the photo image subcommands, namely, -from, -to, -zoom, + * -subsample, -format, -shrink, and -compositingrule. * * Results: * A standard Tcl result. @@ -1608,29 +1615,27 @@ ImgPhotoCmd(clientData, interp, objc, objv) */ static int -ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) - struct SubcommandOptions *optPtr; - /* Information about the options specified - * and the values given is returned here. */ - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - int allowedOptions; /* Indicates which options are valid for - * the current command. */ - int *optIndexPtr; /* Points to a variable containing the - * current index in objv; this variable is - * updated by this procedure. */ - int objc; /* Number of arguments in objv[]. */ - Tcl_Obj *CONST objv[]; /* Arguments to be parsed. */ +ParseSubcommandOptions( + struct SubcommandOptions *optPtr, + /* Information about the options specified and + * the values given is returned here. */ + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + int allowedOptions, /* Indicates which options are valid for the + * current command. */ + int *optIndexPtr, /* Points to a variable containing the current + * index in objv; this variable is updated by + * this function. */ + int objc, /* Number of arguments in objv[]. */ + Tcl_Obj *const objv[]) /* Arguments to be parsed. */ { - int index, c, bit, currentBit; - int length; + int index, c, bit, currentBit, length; + int values[4], numValues, maxValues, argIndex; char *option, **listPtr; - int values[4]; - int numValues, maxValues, argIndex; for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) { /* - * We can have one value specified without an option; - * it goes into optPtr->name. + * We can have one value specified without an option; it goes into + * optPtr->name. */ option = Tcl_GetStringFromObj(objv[index], &length); @@ -1662,24 +1667,24 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) } /* - * If this option is not recognized and allowed, put - * an error message in the interpreter and return. + * If this option is not recognized and allowed, put an error message + * in the interpreter and return. */ if ((allowedOptions & bit) == 0) { Tcl_AppendResult(interp, "unrecognized option \"", Tcl_GetString(objv[index]), - "\": must be ", (char *)NULL); + "\": must be ", NULL); bit = 1; for (listPtr = optionNames; *listPtr != NULL; ++listPtr) { if ((allowedOptions & bit) != 0) { if ((allowedOptions & (bit - 1)) != 0) { - Tcl_AppendResult(interp, ", ", (char *) NULL); + Tcl_AppendResult(interp, ", ", NULL); if ((allowedOptions & ~((bit << 1) - 1)) == 0) { - Tcl_AppendResult(interp, "or ", (char *) NULL); + Tcl_AppendResult(interp, "or ", NULL); } } - Tcl_AppendResult(interp, *listPtr, (char *) NULL); + Tcl_AppendResult(interp, *listPtr, NULL); } bit <<= 1; } @@ -1687,9 +1692,8 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) } /* - * For the -from, -to, -zoom and -subsample options, - * parse the values given. Report an error if too few - * or too many values are given. + * For the -from, -to, -zoom and -subsample options, parse the values + * given. Report an error if too few or too many values are given. */ if (bit == OPT_BACKGROUND) { @@ -1706,14 +1710,13 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) } } else { Tcl_AppendResult(interp, "the \"-background\" option ", - "requires a value", (char *) NULL); + "requires a value", NULL); return TCL_ERROR; } } else if (bit == OPT_FORMAT) { /* - * The -format option takes a single string value. Note - * that parsing this is outside the scope of this - * function. + * The -format option takes a single string value. Note that + * parsing this is outside the scope of this function. */ if (index + 1 < objc) { @@ -1721,13 +1724,13 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) optPtr->format = objv[index]; } else { Tcl_AppendResult(interp, "the \"-format\" option ", - "requires a value", (char *) NULL); + "requires a value", NULL); return TCL_ERROR; } } else if (bit == OPT_COMPOSITE) { /* - * The -compositingrule option takes a single value from - * a well-known set. + * The -compositingrule option takes a single value from a + * well-known set. */ if (index + 1 < objc) { @@ -1735,9 +1738,9 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) * Note that these must match the TK_PHOTO_COMPOSITE_* * constants. */ - static CONST char *compositingRules[] = { - "overlay", "set", - NULL + + static const char *compositingRules[] = { + "overlay", "set", NULL }; index++; @@ -1749,7 +1752,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) *optIndexPtr = index; } else { Tcl_AppendResult(interp, "the \"-compositingrule\" option ", - "requires a value", (char *) NULL); + "requires a value", NULL); return TCL_ERROR; } } else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) { @@ -1760,7 +1763,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) if (argIndex >= objc) { break; } - val = Tcl_GetString(objv[argIndex]); + val = Tcl_GetString(objv[argIndex]); if ((argIndex < objc) && (isdigit(UCHAR(val[0])) || ((val[0] == '-') && isdigit(UCHAR(val[1]))))) { if (Tcl_GetInt(interp, val, &values[numValues]) @@ -1776,7 +1779,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) if (numValues == 0) { Tcl_AppendResult(interp, "the \"", option, "\" option ", "requires one ", maxValues == 2? "or two": "to four", - " integer values", (char *) NULL); + " integer values", NULL); return TCL_ERROR; } *optIndexPtr = (index += numValues); @@ -1793,62 +1796,62 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) } /* - * Check the values given and put them in the appropriate - * field of the SubcommandOptions structure. + * Check the values given and put them in the appropriate field of + * the SubcommandOptions structure. */ switch (bit) { - case OPT_FROM: - if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2) - && ((values[2] < 0) || (values[3] < 0)))) { - Tcl_AppendResult(interp, "value(s) for the -from", - " option must be non-negative", (char *) NULL); - return TCL_ERROR; - } - if (numValues <= 2) { - optPtr->fromX = values[0]; - optPtr->fromY = values[1]; - optPtr->fromX2 = -1; - optPtr->fromY2 = -1; - } else { - optPtr->fromX = MIN(values[0], values[2]); - optPtr->fromY = MIN(values[1], values[3]); - optPtr->fromX2 = MAX(values[0], values[2]); - optPtr->fromY2 = MAX(values[1], values[3]); - } - break; - case OPT_SUBSAMPLE: - optPtr->subsampleX = values[0]; - optPtr->subsampleY = values[1]; - break; - case OPT_TO: - if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2) - && ((values[2] < 0) || (values[3] < 0)))) { - Tcl_AppendResult(interp, "value(s) for the -to", - " option must be non-negative", (char *) NULL); - return TCL_ERROR; - } - if (numValues <= 2) { - optPtr->toX = values[0]; - optPtr->toY = values[1]; - optPtr->toX2 = -1; - optPtr->toY2 = -1; - } else { - optPtr->toX = MIN(values[0], values[2]); - optPtr->toY = MIN(values[1], values[3]); - optPtr->toX2 = MAX(values[0], values[2]); - optPtr->toY2 = MAX(values[1], values[3]); - } - break; - case OPT_ZOOM: - if ((values[0] <= 0) || (values[1] <= 0)) { - Tcl_AppendResult(interp, "value(s) for the -zoom", - " option must be positive", (char *) NULL); - return TCL_ERROR; - } - optPtr->zoomX = values[0]; - optPtr->zoomY = values[1]; - break; + case OPT_FROM: + if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2) + && ((values[2] < 0) || (values[3] < 0)))) { + Tcl_AppendResult(interp, "value(s) for the -from", + " option must be non-negative", NULL); + return TCL_ERROR; + } + if (numValues <= 2) { + optPtr->fromX = values[0]; + optPtr->fromY = values[1]; + optPtr->fromX2 = -1; + optPtr->fromY2 = -1; + } else { + optPtr->fromX = MIN(values[0], values[2]); + optPtr->fromY = MIN(values[1], values[3]); + optPtr->fromX2 = MAX(values[0], values[2]); + optPtr->fromY2 = MAX(values[1], values[3]); + } + break; + case OPT_SUBSAMPLE: + optPtr->subsampleX = values[0]; + optPtr->subsampleY = values[1]; + break; + case OPT_TO: + if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2) + && ((values[2] < 0) || (values[3] < 0)))) { + Tcl_AppendResult(interp, "value(s) for the -to", + " option must be non-negative", NULL); + return TCL_ERROR; + } + if (numValues <= 2) { + optPtr->toX = values[0]; + optPtr->toY = values[1]; + optPtr->toX2 = -1; + optPtr->toY2 = -1; + } else { + optPtr->toX = MIN(values[0], values[2]); + optPtr->toY = MIN(values[1], values[3]); + optPtr->toX2 = MAX(values[0], values[2]); + optPtr->toY2 = MAX(values[1], values[3]); + } + break; + case OPT_ZOOM: + if ((values[0] <= 0) || (values[1] <= 0)) { + Tcl_AppendResult(interp, "value(s) for the -zoom", + " option must be positive", NULL); + return TCL_ERROR; + } + optPtr->zoomX = values[0]; + optPtr->zoomY = values[1]; + break; } } @@ -1867,45 +1870,42 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) * * ImgPhotoConfigureMaster -- * - * This procedure is called when a photo image is created or - * reconfigured. It processes configuration options and resets - * any instances of the image. + * This function is called when a photo image is created or reconfigured. + * It processes configuration options and resets any instances of the + * image. * * Results: - * A standard Tcl return value. If TCL_ERROR is returned then - * an error message is left in the masterPtr->interp's result. + * A standard Tcl return value. If TCL_ERROR is returned then an error + * message is left in the masterPtr->interp's result. * * Side effects: - * Existing instances of the image will be redisplayed to match - * the new configuration options. + * Existing instances of the image will be redisplayed to match the new + * configuration options. * *---------------------------------------------------------------------- */ static int -ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - PhotoMaster *masterPtr; /* Pointer to data structure describing +ImgPhotoConfigureMaster( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + PhotoMaster *masterPtr, /* Pointer to data structure describing * overall photo image to (re)configure. */ - int objc; /* Number of entries in objv. */ - Tcl_Obj *CONST objv[]; /* Pairs of configuration options for image. */ - int flags; /* Flags to pass to Tk_ConfigureWidget, - * such as TK_CONFIG_ARGV_ONLY. */ + int objc, /* Number of entries in objv. */ + Tcl_Obj *const objv[], /* Pairs of configuration options for image. */ + int flags) /* Flags to pass to Tk_ConfigureWidget, such + * as TK_CONFIG_ARGV_ONLY. */ { PhotoInstance *instancePtr; - CONST char *oldFileString, *oldPaletteString; + const char *oldFileString, *oldPaletteString; Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL; - int length, i, j; + Tcl_Obj *tempdata, *tempformat; + int length, i, j, result, imageWidth, imageHeight, oldformat; double oldGamma; - int result; Tcl_Channel chan; Tk_PhotoImageFormat *imageFormat; - int imageWidth, imageHeight; - CONST char **args; - int oldformat; - Tcl_Obj *tempdata, *tempformat; + const char **args; - args = (CONST char **) ckalloc((objc + 1) * sizeof(char *)); + args = (const char **) ckalloc((objc + 1) * sizeof(char *)); for (i = 0, j = 0; i < objc; i++,j++) { args[j] = Tcl_GetStringFromObj(objv[i], &length); if ((length > 1) && (args[j][0] == '-')) { @@ -1916,7 +1916,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) j--; } else { Tcl_AppendResult(interp, - "value for \"-data\" missing", (char *) NULL); + "value for \"-data\" missing", NULL); return TCL_ERROR; } } else if ((args[j][1] == 'f') && @@ -1926,7 +1926,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) j--; } else { Tcl_AppendResult(interp, - "value for \"-format\" missing", (char *) NULL); + "value for \"-format\" missing", NULL); return TCL_ERROR; } } @@ -1934,12 +1934,10 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } /* - * Save the current values for fileString and dataString, so we - * can tell if the user specifies them anew. - * IMPORTANT: if the format changes we have to interpret - * "-file" and "-data" again as well!!!!!!! It might be - * that the format string influences how "-data" or "-file" - * is interpreted. + * Save the current values for fileString and dataString, so we can tell + * if the user specifies them anew. IMPORTANT: if the format changes we + * have to interpret "-file" and "-data" again as well! It might be that + * the format string influences how "-data" or "-file" is interpreted. */ oldFileString = masterPtr->fileString; @@ -1970,8 +1968,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) ckfree((char *) args); /* - * Regard the empty string for -file, -data or -format as the null - * value. + * Regard the empty string for -file, -data or -format as the null value. */ if ((masterPtr->fileString != NULL) && (masterPtr->fileString[0] == 0)) { @@ -1980,9 +1977,10 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } if (data) { /* - * Force into ByteArray format, which most (all) image handlers - * will use anyway. Empty length means ignore the -data option. + * Force into ByteArray format, which most (all) image handlers will + * use anyway. Empty length means ignore the -data option. */ + (void) Tcl_GetByteArrayFromObj(data, &length); if (length) { Tcl_IncrRefCount(data); @@ -1996,9 +1994,10 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } if (format) { /* - * Stringify to ignore -format "". It may come in as a list or - * other object. + * Stringify to ignore -format "". It may come in as a list or other + * object. */ + (void) Tcl_GetStringFromObj(format, &length); if (length) { Tcl_IncrRefCount(format); @@ -2011,47 +2010,47 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) masterPtr->format = format; } /* - * Set the image to the user-requested size, if any, - * and make sure storage is correctly allocated for this image. + * Set the image to the user-requested size, if any, and make sure storage + * is correctly allocated for this image. */ if (ImgPhotoSetSize(masterPtr, masterPtr->width, masterPtr->height) != TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); goto errorExit; } /* - * Read in the image from the file or string if the user has - * specified the -file or -data option. + * 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) || (masterPtr->format != oldFormat))) { - /* - * Prevent file system access in a safe interpreter. - */ + /* + * Prevent file system access in a safe interpreter. + */ - if (Tcl_IsSafe(interp)) { + if (Tcl_IsSafe(interp)) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "can't get image from a file in a safe interpreter", - (char *) NULL); + Tcl_AppendResult(interp, + "can't get image from a file in a safe interpreter", NULL); goto errorExit; - } - + } + chan = Tcl_OpenFileChannel(interp, masterPtr->fileString, "r", 0); if (chan == NULL) { goto errorExit; } + /* * -translation binary also sets -encoding binary */ - if ((Tcl_SetChannelOption(interp, chan, + + if ((Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) || (MatchFileFormat(interp, chan, masterPtr->fileString, masterPtr->format, &imageFormat, &imageWidth, @@ -2063,8 +2062,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) if (result != TCL_OK) { Tcl_Close(NULL, chan); Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); goto errorExit; } tempformat = masterPtr->format; @@ -2072,9 +2070,8 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) tempformat = (Tcl_Obj *) Tcl_GetString(tempformat); } result = (*imageFormat->fileReadProc)(interp, chan, - masterPtr->fileString, tempformat, - (Tk_PhotoHandle) masterPtr, 0, 0, - imageWidth, imageHeight, 0, 0); + masterPtr->fileString, tempformat, (Tk_PhotoHandle) masterPtr, + 0, 0, imageWidth, imageHeight, 0, 0); Tcl_Close(NULL, chan); if (result != TCL_OK) { goto errorExit; @@ -2095,8 +2092,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } if (ImgPhotoSetSize(masterPtr, imageWidth, imageHeight) != TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); goto errorExit; } tempformat = masterPtr->format; @@ -2131,9 +2127,9 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } /* - * 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. + * 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; @@ -2142,8 +2138,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } /* - * Inform the generic image code that the image - * has (potentially) changed. + * Inform the generic image code that the image has (potentially) changed. */ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width, @@ -2176,24 +2171,24 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) * * 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. + * This function 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. + * Generates errors via Tcl_BackgroundError if there are problems in + * setting up the instance. * *---------------------------------------------------------------------- */ static void -ImgPhotoConfigureInstance(instancePtr) - PhotoInstance *instancePtr; /* Instance to reconfigure. */ +ImgPhotoConfigureInstance( + PhotoInstance *instancePtr) /* Instance to reconfigure. */ { PhotoMaster *masterPtr = instancePtr->masterPtr; XImage *imagePtr; @@ -2202,10 +2197,9 @@ ImgPhotoConfigureInstance(instancePtr) 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 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]) @@ -2217,9 +2211,9 @@ ImgPhotoConfigureInstance(instancePtr) 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. + * 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; @@ -2238,8 +2232,8 @@ ImgPhotoConfigureInstance(instancePtr) GetColorTable(instancePtr); /* - * Create a new XImage structure for sending data to - * the X server, if necessary. + * Create a new XImage structure for sending data to the X server, if + * necessary. */ if (instancePtr->colorTablePtr->flags & BLACK_AND_WHITE) { @@ -2255,7 +2249,7 @@ ImgPhotoConfigureInstance(instancePtr) } imagePtr = XCreateImage(instancePtr->display, instancePtr->visualInfo.visual, (unsigned) bitsPerPixel, - (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, (char *) NULL, + (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, NULL, 1, 1, 32, 0); instancePtr->imagePtr = imagePtr; @@ -2278,11 +2272,10 @@ ImgPhotoConfigureInstance(instancePtr) } /* - * 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 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) @@ -2310,62 +2303,60 @@ ImgPhotoConfigureInstance(instancePtr) * * ImgPhotoGet -- * - * This procedure is called for each use of a photo image in a - * widget. + * This function 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. + * 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). + * A data structure is set up for the instance (or, an existing instance + * is re-used for the new one). * *---------------------------------------------------------------------- */ static ClientData -ImgPhotoGet(tkwin, masterData) - Tk_Window tkwin; /* Window in which the instance will be +ImgPhotoGet( + Tk_Window tkwin, /* Window in which the instance will be * used. */ - ClientData masterData; /* Pointer to our master structure for the + ClientData masterData) /* Pointer to our master structure for the * image. */ { PhotoMaster *masterPtr = (PhotoMaster *) masterData; PhotoInstance *instancePtr; Colormap colormap; - int mono, nRed, nGreen, nBlue; + int mono, nRed, nGreen, nBlue, numVisuals; XVisualInfo visualInfo, *visInfoPtr; char buf[TCL_INTEGER_SPACE * 3]; - int numVisuals; XColor *white, *black; XGCValues gcValues; /* - * Table of "best" choices for palette for PseudoColor displays - * with between 3 and 15 bits/pixel. + * Table of "best" choices for palette for PseudoColor displays with + * between 3 and 15 bits/pixel. */ - static int paletteChoice[13][3] = { + static const 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 */} + {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. + * See if there is already an instance for windows using the same + * colormap. If so then just re-use it. */ colormap = Tk_Colormap(tkwin); @@ -2373,7 +2364,6 @@ ImgPhotoGet(tkwin, masterData) instancePtr = instancePtr->nextPtr) { if ((colormap == instancePtr->colormap) && (Tk_Display(tkwin) == instancePtr->display)) { - /* * Re-use this instance. */ @@ -2395,8 +2385,8 @@ ImgPhotoGet(tkwin, masterData) } /* - * The image isn't already in use in a window with the same colormap. - * Make a new instance of the image. + * 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)); @@ -2415,53 +2405,51 @@ ImgPhotoGet(tkwin, masterData) masterPtr->instancePtr = instancePtr; /* - * Obtain information about the visual and decide on the - * default palette. + * 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); + if (visInfoPtr == NULL) { + Tcl_Panic("ImgPhotoGet couldn't find visual for window"); + } + 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"); - } + 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) { + const 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); sprintf(buf, ((mono) ? "%d": "%d/%d/%d"), nRed, nGreen, nBlue); instancePtr->defaultPalette = Tk_GetUid(buf); @@ -2483,8 +2471,8 @@ ImgPhotoGet(tkwin, masterData) GCForeground|GCBackground|GCGraphicsExposures, &gcValues); /* - * Set configuration options and finish the initialization of the instance. - * This will also dither the image if necessary. + * Set configuration options and finish the initialization of the + * instance. This will also dither the image if necessary. */ ImgPhotoConfigureInstance(instancePtr); @@ -2506,9 +2494,9 @@ ImgPhotoGet(tkwin, masterData) * * ToggleComplexAlphaIfNeeded -- * - * This procedure is called when an image is modified to - * check if any partially transparent pixels exist, which - * requires blending instead of straight copy. + * This function is called when an image is modified to check if any + * partially transparent pixels exist, which requires blending instead of + * straight copy. * * Results: * None. @@ -2520,19 +2508,21 @@ ImgPhotoGet(tkwin, masterData) */ static int -ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr) +ToggleComplexAlphaIfNeeded( + PhotoMaster *mPtr) { size_t len = MAX(mPtr->userWidth, mPtr->width) * - MAX(mPtr->userHeight, mPtr->height) * 4; - unsigned char *c = mPtr->pix32; + MAX(mPtr->userHeight, mPtr->height) * 4; + unsigned char *c = mPtr->pix32; unsigned char *end = c + len; /* * Set the COMPLEX_ALPHA flag if we have an image with partially * transparent bits. */ + mPtr->flags &= ~COMPLEX_ALPHA; - c += 3; /* start at first alpha byte */ + c += 3; /* Start at first alpha byte. */ for (; c < end; c += 4) { if (*c && *c != 255) { mPtr->flags |= COMPLEX_ALPHA; @@ -2547,8 +2537,13 @@ ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr) * * ImgPhotoBlendComplexAlpha -- * - * This procedure is called when an image with partially - * transparent pixels must be drawn over another image. + * This function is called when an image with partially transparent + * pixels must be drawn over another image. It blends the photo data onto + * a local copy of the surface that we are drawing on, *including* the + * pixels drawn by everything that should be drawn underneath the image. + * + * Much of this code has hard-coded values in for speed because this + * routine is performance critical for complex image drawing. * * Results: * None. @@ -2556,53 +2551,61 @@ ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr) * Side effects: * Background image passed in gets drawn over with image data. * - *---------------------------------------------------------------------- - */ - -/* - * This should work on all platforms that set mask and shift data properly - * from the visualInfo. - * RGB is really only a 24+ bpp version whereas RGB15 is the correct version - * and works for 15bpp+, but it slower, so it's only used for 15bpp+. + * Notes: + * This should work on all platforms that set mask and shift data + * properly from the visualInfo. RGB is really only a 24+ bpp version + * whereas RGB15 is the correct version and works for 15bpp+, but it + * slower, so it's only used for 15bpp+. + * + * Note that Win32 pre-defines those operations that we really need. * - * Note that Win32 pre-defines those operations that we really need. + *---------------------------------------------------------------------- */ #ifndef __WIN32__ -#define GetRValue(rgb) (UCHAR((rgb & red_mask) >> red_shift)) -#define GetGValue(rgb) (UCHAR((rgb & green_mask) >> green_shift)) -#define GetBValue(rgb) (UCHAR((rgb & blue_mask) >> blue_shift)) -#define RGB(r,g,b) ((unsigned)((UCHAR(r)<<red_shift)|(UCHAR(g)<<green_shift)|(UCHAR(b)<<blue_shift))) -#define RGB15(r,g,b) ((unsigned)(((r*red_mask/255)&red_mask)|((g*green_mask/255)&green_mask)|((b*blue_mask/255)&blue_mask))) +#define GetRValue(rgb) (UCHAR(((rgb) & red_mask) >> red_shift)) +#define GetGValue(rgb) (UCHAR(((rgb) & green_mask) >> green_shift)) +#define GetBValue(rgb) (UCHAR(((rgb) & blue_mask) >> blue_shift)) +#define RGB(r, g, b) ((unsigned)( \ + (UCHAR(r) << red_shift) | \ + (UCHAR(g) << green_shift) | \ + (UCHAR(b) << blue_shift) )) +#define RGB15(r, g, b) ((unsigned)( \ + (((r) * red_mask / 255) & red_mask) | \ + (((g) * green_mask / 255) & green_mask) | \ + (((b) * blue_mask / 255) & blue_mask) )) #endif /* !__WIN32__ */ static void -ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) - XImage *bgImg; /* background image to draw on */ - PhotoInstance *iPtr; /* image instance to draw */ - int xOffset, yOffset; /* X & Y offset into image instance to draw */ - int width, height; /* width & height of image to draw */ +ImgPhotoBlendComplexAlpha( + XImage *bgImg, /* Background image to draw on. */ + PhotoInstance *iPtr, /* Image instance to draw. */ + int xOffset, int yOffset, /* X & Y offset into image instance to + * draw. */ + int width, int height) /* Width & height of image to draw. */ { int x, y, line; unsigned long pixel; - unsigned char r, g, b, alpha, unalpha; + unsigned char r, g, b, alpha, unalpha, *masterPtr; unsigned char *alphaAr = iPtr->masterPtr->pix32; - unsigned char *masterPtr; /* - * This blending is an integer version of the Source-Over - * compositing rule (see Porter&Duff, "Compositing Digital - * Images", proceedings of SIGGRAPH 1984) that has been hard-coded - * (for speed) to work with targetting a solid surface. + * This blending is an integer version of the Source-Over compositing rule + * (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH + * 1984) that has been hard-coded (for speed) to work with targetting a + * solid surface. + * + * The 'unalpha' field must be 255-alpha; it is separated out to encourage + * more efficient compilation. */ #define ALPHA_BLEND(bgPix, imgPix, alpha, unalpha) \ ((bgPix * unalpha + imgPix * alpha) / 255) /* - * We have to get the mask and shift info from the visual on - * non-Win32 so that the macros Get*Value(), RGB() and RGB15() - * work correctly. This might be cached for better performance. + * We have to get the mask and shift info from the visual on non-Win32 so + * that the macros Get*Value(), RGB() and RGB15() work correctly. This + * might be cached for better performance. */ #ifndef __WIN32__ @@ -2628,9 +2631,9 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) #endif /* !__WIN32__ */ /* - * Only unix requires the special case for <24bpp. It varies with - * 3 extra shifts and uses RGB15. The 24+bpp version could also - * then be further optimized. + * Only UNIX requires the special case for <24bpp. It varies with 3 extra + * shifts and uses RGB15. The 24+bpp version could also then be further + * optimized. */ #if !(defined(__WIN32__) || defined(MAC_OSX_TK)) @@ -2645,14 +2648,17 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) for (x = 0; x < width; x++) { masterPtr = alphaAr + ((line + x + xOffset) * 4); alpha = masterPtr[3]; + /* * Ignore pixels that are fully transparent */ + if (alpha) { /* * We could perhaps be more efficient than XGetPixel for * 24 and 32 bit displays, but this seems "fast enough". */ + r = masterPtr[0]; g = masterPtr[1]; b = masterPtr[2]; @@ -2660,13 +2666,14 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) /* * Only blend pixels that have some transparency */ + unsigned char ra, ga, ba; pixel = XGetPixel(bgImg, x, y); ra = GetRValue(pixel) << red_mlen; ga = GetGValue(pixel) << green_mlen; ba = GetBValue(pixel) << blue_mlen; - unalpha = 255 - alpha; + unalpha = 255 - alpha; /* Calculate once. */ r = ALPHA_BLEND(ra, r, alpha, unalpha); g = ALPHA_BLEND(ga, g, alpha, unalpha); b = ALPHA_BLEND(ba, b, alpha, unalpha); @@ -2684,14 +2691,17 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) for (x = 0; x < width; x++) { masterPtr = alphaAr + ((line + x + xOffset) * 4); alpha = masterPtr[3]; + /* * Ignore pixels that are fully transparent */ + if (alpha) { /* - * We could perhaps be more efficient than XGetPixel for - * 24 and 32 bit displays, but this seems "fast enough". + * We could perhaps be more efficient than XGetPixel for 24 + * and 32 bit displays, but this seems "fast enough". */ + r = masterPtr[0]; g = masterPtr[1]; b = masterPtr[2]; @@ -2699,13 +2709,14 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) /* * Only blend pixels that have some transparency */ + unsigned char ra, ga, ba; pixel = XGetPixel(bgImg, x, y); ra = GetRValue(pixel); ga = GetGValue(pixel); ba = GetBValue(pixel); - unalpha = 255 - alpha; + unalpha = 255 - alpha; /* Calculate once. */ r = ALPHA_BLEND(ra, r, alpha, unalpha); g = ALPHA_BLEND(ga, g, alpha, unalpha); b = ALPHA_BLEND(ba, b, alpha, unalpha); @@ -2714,7 +2725,6 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) } } } - #undef ALPHA_BLEND } @@ -2723,7 +2733,7 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) * * ImgPhotoDisplay -- * - * This procedure is invoked to draw a photo image. + * This function is invoked to draw a photo image. * * Results: * None. @@ -2735,48 +2745,31 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) */ static void -ImgPhotoDisplay(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. */ +ImgPhotoDisplay( + ClientData clientData, /* Pointer to PhotoInstance structure 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, int imageY, /* Upper-left corner of region within image to + * draw. */ + int width, int height, /* Dimensions of region within image to + * draw. */ + int drawableX,int drawableY)/* Coordinates within drawable that correspond + * to imageX and imageY. */ { PhotoInstance *instancePtr = (PhotoInstance *) clientData; XVisualInfo visInfo = instancePtr->visualInfo; /* - * If there's no pixmap, it means that an error occurred - * while creating the image instance so it can't be displayed. + * 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; } - /* - * Check for bogus widths/heights. This prevents us from calling - * XGetImage with a zero size, which it does not like. [Bug 979239] - */ - - if (width < 1 || height < 1) { - return; - } - - if ( -#if defined(MAC_TCL) - /* - * The retrieval of bgImg is currently not functional on OS9 - * so skip attempts to alpha blend. - */ - 0 && -#endif - (instancePtr->masterPtr->flags & COMPLEX_ALPHA) + if ((instancePtr->masterPtr->flags & COMPLEX_ALPHA) && visInfo.depth >= 15 && (visInfo.class == DirectColor || visInfo.class == TrueColor)) { Tk_ErrorHandler handler; @@ -2786,11 +2779,14 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, * Create an error handler to suppress the case where the input was * not properly constrained, which can cause an X error. [Bug 979239] */ - handler = Tk_CreateErrorHandler(display, -1, -1, -1, - (Tk_ErrorProc *) NULL, (ClientData) NULL); + + handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, + (ClientData) NULL); + /* * Pull the current background from the display to blend with */ + bgImg = XGetImage(display, drawable, drawableX, drawableY, (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap); if (bgImg == NULL) { @@ -2798,13 +2794,14 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, return; } - ImgPhotoBlendComplexAlpha(bgImg, instancePtr, - imageX, imageY, width, height); + ImgPhotoBlendComplexAlpha(bgImg, instancePtr, imageX, imageY, width, + height); /* - * Color info is unimportant as we only do this operation for - * depth >= 15. + * Color info is unimportant as we only do this operation for depth >= + * 15. */ + TkPutImage(NULL, 0, display, drawable, instancePtr->gc, bgImg, 0, 0, drawableX, drawableY, (unsigned int) width, (unsigned int) height); @@ -2812,21 +2809,22 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, Tk_DeleteErrorHandler(handler); } else { /* - * 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. + * 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); + + TkSetRegion(display, instancePtr->gc, + instancePtr->masterPtr->validRegion); XSetClipOrigin(display, instancePtr->gc, drawableX - imageX, - drawableY - imageY); + drawableY - imageY); XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc, - imageX, imageY, (unsigned) width, (unsigned) height, - drawableX, drawableY); + imageX, imageY, (unsigned) width, (unsigned) height, + drawableX, drawableY); XSetClipMask(display, instancePtr->gc, None); XSetClipOrigin(display, instancePtr->gc, 0, 0); } - XFlush (display); + XFlush(display); } /* @@ -2834,10 +2832,9 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, * * 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. + * This function 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. @@ -2849,10 +2846,11 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, */ static void -ImgPhotoFree(clientData, display) - ClientData clientData; /* Pointer to PhotoInstance structure for - * for instance to be displayed. */ - Display *display; /* Display containing window that used image. */ +ImgPhotoFree( + ClientData clientData, /* Pointer to PhotoInstance structure for + * instance to be displayed. */ + Display *display) /* Display containing window that used + * image. */ { PhotoInstance *instancePtr = (PhotoInstance *) clientData; ColorTable *colorPtr; @@ -2863,17 +2861,17 @@ ImgPhotoFree(clientData, display) } /* - * 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. + * 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); } @@ -2882,8 +2880,8 @@ ImgPhotoFree(clientData, display) * * ImgPhotoDelete -- * - * This procedure is called by the image code to delete the - * master structure for an image. + * This function is called by the image code to delete the master + * structure for an image. * * Results: * None. @@ -2895,16 +2893,16 @@ ImgPhotoFree(clientData, display) */ static void -ImgPhotoDelete(masterData) - ClientData masterData; /* Pointer to PhotoMaster structure for - * image. Must not have any more instances. */ +ImgPhotoDelete( + 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_Panic("tried to delete photo image when instances still exist"); } Tcl_CancelIdleCall(DisposeInstance, (ClientData) instancePtr); DisposeInstance((ClientData) instancePtr); @@ -2925,7 +2923,7 @@ ImgPhotoDelete(masterData) if (masterPtr->format != NULL) { Tcl_DecrRefCount(masterPtr->format); } - Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0); + Tk_FreeOptions(configSpecs, (char *) masterPtr, NULL, 0); ckfree((char *) masterPtr); } @@ -2934,8 +2932,8 @@ ImgPhotoDelete(masterData) * * ImgPhotoCmdDeletedProc -- * - * This procedure is invoked when the image command for an image - * is deleted. It deletes the image. + * This function is invoked when the image command for an image is + * deleted. It deletes the image. * * Results: * None. @@ -2947,8 +2945,8 @@ ImgPhotoDelete(masterData) */ static void -ImgPhotoCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to PhotoMaster structure for +ImgPhotoCmdDeletedProc( + ClientData clientData) /* Pointer to PhotoMaster structure for * image. */ { PhotoMaster *masterPtr = (PhotoMaster *) clientData; @@ -2964,13 +2962,13 @@ ImgPhotoCmdDeletedProc(clientData) * * 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. + * This function 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: - * TCL_OK if successful, TCL_ERROR if failure occurred (currently - * just with memory allocation.) + * TCL_OK if successful, TCL_ERROR if failure occurred (currently just + * with memory allocation.) * * Side effects: * Storage gets reallocated, for the master and all its instances. @@ -2979,9 +2977,9 @@ ImgPhotoCmdDeletedProc(clientData) */ static int -ImgPhotoSetSize(masterPtr, width, height) - PhotoMaster *masterPtr; - int width, height; +ImgPhotoSetSize( + PhotoMaster *masterPtr, + int width, int height) { unsigned char *newPix32 = NULL; int h, offset, pitch; @@ -3000,19 +2998,22 @@ ImgPhotoSetSize(masterPtr, width, height) pitch = width * 4; /* - * Test if we're going to (re)allocate the main buffer now, so - * that any failures will leave the photo unchanged. + * Test if we're going to (re)allocate the main buffer now, so that any + * failures will leave the photo unchanged. */ + if ((width != masterPtr->width) || (height != masterPtr->height) || (masterPtr->pix32 == NULL)) { /* * Not a u-long, but should be one. */ + unsigned /*long*/ newPixSize = (unsigned /*long*/) (height * pitch); /* * Some mallocs() really hate allocating zero bytes. [Bug 619544] */ + if (newPixSize == 0) { newPix32 = NULL; } else { @@ -3024,8 +3025,8 @@ ImgPhotoSetSize(masterPtr, width, height) } /* - * We have to trim the valid region if it is currently - * larger than the new image size. + * We have to trim the valid region if it is currently larger than the new + * image size. */ TkClipBox(masterPtr->validRegion, &validBox); @@ -3044,36 +3045,35 @@ ImgPhotoSetSize(masterPtr, width, height) } /* - * Use the reallocated storage (allocation above) for the 32-bit - * image and copy over valid regions. Note that this test is true - * precisely when the allocation has already been done. + * Use the reallocated storage (allocation above) for the 32-bit image and + * copy over valid regions. Note that this test is true precisely when the + * allocation has already been done. */ + if (newPix32 != NULL) { /* - * 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. + * 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->pix32 != NULL) && ((width == masterPtr->width) || (width == validBox.width))) { if (validBox.y > 0) { - memset((VOID *) newPix32, 0, (size_t) (validBox.y * pitch)); + memset(newPix32, 0, (size_t) (validBox.y * pitch)); } h = validBox.y + validBox.height; if (h < height) { - memset((VOID *) (newPix32 + h * pitch), 0, - (size_t) ((height - h) * pitch)); + memset(newPix32 + h*pitch, 0, (size_t) ((height - h) * pitch)); } } else { - memset((VOID *) newPix32, 0, (size_t) (height * pitch)); + memset(newPix32, 0, (size_t) (height * pitch)); } if (masterPtr->pix32 != NULL) { - /* - * Copy the common area over to the new array array and - * free the old array. + * Copy the common area over to the new array array and free the + * old array. */ if (width == masterPtr->width) { @@ -3083,12 +3083,10 @@ ImgPhotoSetSize(masterPtr, width, height) */ offset = validBox.y * pitch; - memcpy((VOID *) (newPix32 + offset), - (VOID *) (masterPtr->pix32 + offset), + memcpy(newPix32 + offset, masterPtr->pix32 + 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. */ @@ -3097,8 +3095,7 @@ ImgPhotoSetSize(masterPtr, width, height) srcPtr = masterPtr->pix32 + (validBox.y * masterPtr->width + validBox.x) * 4; for (h = validBox.height; h > 0; h--) { - memcpy((VOID *) destPtr, (VOID *) srcPtr, - (size_t) (validBox.width * 4)); + memcpy(destPtr, srcPtr, (size_t) (validBox.width * 4)); destPtr += width * 4; srcPtr += masterPtr->width * 4; } @@ -3112,8 +3109,8 @@ ImgPhotoSetSize(masterPtr, width, height) masterPtr->height = height; /* - * Dithering will be correct up to the end of the last - * pre-existing complete scanline. + * Dithering will be correct up to the end of the last pre-existing + * complete scanline. */ if ((validBox.x > 0) || (validBox.y > 0)) { @@ -3150,9 +3147,9 @@ ImgPhotoSetSize(masterPtr, width, height) * * 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. + * This function 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. @@ -3164,13 +3161,11 @@ ImgPhotoSetSize(masterPtr, width, height) */ static void -ImgPhotoInstanceSetSize(instancePtr) - PhotoInstance *instancePtr; /* Instance whose size is to be - * changed. */ +ImgPhotoInstanceSetSize( + PhotoInstance *instancePtr) /* Instance whose size is to be changed. */ { PhotoMaster *masterPtr; - schar *newError; - schar *errSrcPtr, *errDestPtr; + schar *newError, *errSrcPtr, *errDestPtr; int h, offset; XRectangle validBox; Pixmap newPixmap; @@ -3183,22 +3178,21 @@ ImgPhotoInstanceSetSize(instancePtr) || (instancePtr->pixels == None)) { newPixmap = Tk_GetPixmap(instancePtr->display, RootWindow(instancePtr->display, - instancePtr->visualInfo.screen), + instancePtr->visualInfo.screen), (masterPtr->width > 0) ? masterPtr->width: 1, (masterPtr->height > 0) ? masterPtr->height: 1, instancePtr->visualInfo.depth); - if (!newPixmap) { - panic("Fail to create pixmap with Tk_GetPixmap in ImgPhotoInstanceSetSize.\n"); - return; - } + if (!newPixmap) { + Tcl_Panic("Fail to create pixmap with Tk_GetPixmap in ImgPhotoInstanceSetSize.\n"); + } /* * 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. + * 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); @@ -3207,6 +3201,7 @@ ImgPhotoInstanceSetSize(instancePtr) /* * 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); @@ -3224,54 +3219,51 @@ ImgPhotoInstanceSetSize(instancePtr) masterPtr->height * masterPtr->width * 3 * sizeof(schar)); /* - * Zero the new array so that we don't get bogus error - * values propagating into areas we dither later. + * Zero the new array so that we don't get bogus error values + * propagating into areas we dither later. */ if ((instancePtr->error != NULL) && ((instancePtr->width == masterPtr->width) || (validBox.width == masterPtr->width))) { if (validBox.y > 0) { - memset((VOID *) newError, 0, (size_t) + memset(newError, 0, (size_t) validBox.y * masterPtr->width * 3 * sizeof(schar)); } h = validBox.y + validBox.height; if (h < masterPtr->height) { - memset((VOID *) (newError + h * masterPtr->width * 3), 0, + memset(newError + h*masterPtr->width*3, 0, (size_t) (masterPtr->height - h) * masterPtr->width * 3 * sizeof(schar)); } } else { - memset((VOID *) newError, 0, (size_t) - masterPtr->height * masterPtr->width * 3 * sizeof(schar)); + memset(newError, 0, (size_t) + masterPtr->height * masterPtr->width *3*sizeof(schar)); } } else { newError = NULL; } if (instancePtr->error != NULL) { - /* - * Copy the common area over to the new array - * and free the old array. + * Copy the common area over to the new array and free the old + * array. */ if (masterPtr->width == instancePtr->width) { - offset = validBox.y * masterPtr->width * 3; - memcpy((VOID *) (newError + offset), - (VOID *) (instancePtr->error + offset), + memcpy(newError + offset, instancePtr->error + offset, (size_t) (validBox.height * masterPtr->width * 3 * sizeof(schar))); } else if (validBox.width > 0 && validBox.height > 0) { + errDestPtr = newError + + (validBox.y * masterPtr->width + validBox.x) * 3; + errSrcPtr = instancePtr->error + + (validBox.y * instancePtr->width + validBox.x) * 3; - errDestPtr = newError - + (validBox.y * masterPtr->width + validBox.x) * 3; - errSrcPtr = instancePtr->error - + (validBox.y * instancePtr->width + validBox.x) * 3; for (h = validBox.height; h > 0; --h) { - memcpy((VOID *) errDestPtr, (VOID *) errSrcPtr, + memcpy(errDestPtr, errSrcPtr, validBox.width * 3 * sizeof(schar)); errDestPtr += masterPtr->width * 3; errSrcPtr += instancePtr->width * 3; @@ -3292,9 +3284,8 @@ ImgPhotoInstanceSetSize(instancePtr) * * IsValidPalette -- * - * This procedure is called to check whether a value given for - * the -palette option is valid for a particular instance - * of a photo image. + * This function is called to check whether a value given for the + * -palette option is valid for a particular instance of a photo image. * * Results: * A boolean value: 1 if the palette is acceptable, 0 otherwise. @@ -3306,17 +3297,16 @@ ImgPhotoInstanceSetSize(instancePtr) */ static int -IsValidPalette(instancePtr, palette) - PhotoInstance *instancePtr; /* Instance to which the palette - * specification is to be applied. */ - CONST char *palette; /* Palette specification string. */ +IsValidPalette( + PhotoInstance *instancePtr, /* Instance to which the palette specification + * is to be applied. */ + const char *palette) /* Palette specification string. */ { int nRed, nGreen, nBlue, mono, numColors; char *endp; /* - * First parse the specification: it must be of the form - * %d or %d/%d/%d. + * First parse the specification: it must be of the form %d or %d/%d/%d. */ nRed = strtol(palette, &endp, 10); @@ -3345,32 +3335,30 @@ IsValidPalette(instancePtr, palette) } switch (instancePtr->visualInfo.class) { - case DirectColor: - case TrueColor: - if ((nRed > (1 << CountBits(instancePtr->visualInfo.red_mask))) - || (nGreen > (1 - << CountBits(instancePtr->visualInfo.green_mask))) - || (nBlue > (1 - << CountBits(instancePtr->visualInfo.blue_mask)))) { - return 0; - } - break; - case PseudoColor: - case StaticColor: - numColors = nRed; - if (!mono) { - numColors *= nGreen*nBlue; - } - if (numColors > (1 << instancePtr->visualInfo.depth)) { - return 0; - } - break; - case GrayScale: - case StaticGray: - if (!mono || (nRed > (1 << instancePtr->visualInfo.depth))) { - return 0; - } - break; + case DirectColor: + case TrueColor: + if ((nRed > (1 << CountBits(instancePtr->visualInfo.red_mask))) + || (nGreen>(1<<CountBits(instancePtr->visualInfo.green_mask))) + || (nBlue>(1<<CountBits(instancePtr->visualInfo.blue_mask)))) { + return 0; + } + break; + case PseudoColor: + case StaticColor: + numColors = nRed; + if (!mono) { + numColors *= nGreen*nBlue; + } + if (numColors > (1 << instancePtr->visualInfo.depth)) { + return 0; + } + break; + case GrayScale: + case StaticGray: + if (!mono || (nRed > (1 << instancePtr->visualInfo.depth))) { + return 0; + } + break; } return 1; @@ -3381,7 +3369,7 @@ IsValidPalette(instancePtr, palette) * * CountBits -- * - * This procedure counts how many bits are set to 1 in `mask'. + * This function counts how many bits are set to 1 in `mask'. * * Results: * The integer number of bits. @@ -3393,13 +3381,14 @@ IsValidPalette(instancePtr, palette) */ static int -CountBits(mask) - pixel mask; /* Value to count the 1 bits in. */ +CountBits( + pixel mask) /* Value to count the 1 bits in. */ { int n; - for( n = 0; mask != 0; mask &= mask - 1 ) + for (n=0 ; mask!=0 ; mask&=mask-1) { n++; + } return n; } @@ -3408,28 +3397,27 @@ CountBits(mask) * * GetColorTable -- * - * This procedure is called to allocate a table of colormap - * information for an instance of a photo image. Only one such - * table is allocated for all photo instances using the same - * display, colormap, palette and gamma values, so that the - * application need only request a set of colors from the X - * server once for all such photo widgets. This procedure - * maintains a hash table to find previously-allocated + * This function is called to allocate a table of colormap information + * for an instance of a photo image. Only one such table is allocated for + * all photo instances using the same display, colormap, palette and + * gamma values, so that the application need only request a set of + * colors from the X server once for all such photo widgets. This + * function maintains a hash table to find previously-allocated * ColorTables. * * Results: * None. * * Side effects: - * A new ColorTable may be allocated and placed in the hash - * table, and have colors allocated for it. + * A new ColorTable may be allocated and placed in the hash table, and + * have colors allocated for it. * *---------------------------------------------------------------------- */ static void -GetColorTable(instancePtr) - PhotoInstance *instancePtr; /* Instance needing a color table. */ +GetColorTable( + PhotoInstance *instancePtr) /* Instance needing a color table. */ { ColorTable *colorPtr; Tcl_HashEntry *entry; @@ -3440,7 +3428,7 @@ GetColorTable(instancePtr) * Look for an existing ColorTable in the hash table. */ - memset((VOID *) &id, 0, sizeof(id)); + memset(&id, 0, sizeof(id)); id.display = instancePtr->display; id.colormap = instancePtr->colormap; id.palette = instancePtr->palette; @@ -3457,7 +3445,6 @@ GetColorTable(instancePtr) */ colorPtr = (ColorTable *) Tcl_GetHashValue(entry); - } else { /* * No color table currently available; need to make one. @@ -3466,16 +3453,15 @@ GetColorTable(instancePtr) colorPtr = (ColorTable *) ckalloc(sizeof(ColorTable)); /* - * The following line of code should not normally be needed due - * to the assignment in the following line. However, it compensates - * for bugs in some compilers (HP, for example) where - * sizeof(ColorTable) is 24 but the assignment only copies 20 bytes, - * leaving 4 bytes uninitialized; these cause problems when using - * the id for lookups in imgPhotoColorHash, and can result in - * core dumps. + * The following line of code should not normally be needed due to the + * assignment in the following line. However, it compensates for bugs + * in some compilers (HP, for example) where sizeof(ColorTable) is 24 + * but the assignment only copies 20 bytes, leaving 4 bytes + * uninitialized; these cause problems when using the id for lookups + * in imgPhotoColorHash, and can result in core dumps. */ - memset((VOID *) &colorPtr->id, 0, sizeof(ColorTableId)); + memset(&colorPtr->id, 0, sizeof(ColorTableId)); colorPtr->id = id; Tk_PreserveColormap(colorPtr->id.display, colorPtr->id.colormap); colorPtr->flags = 0; @@ -3510,30 +3496,30 @@ GetColorTable(instancePtr) * * FreeColorTable -- * - * This procedure is called when an instance ceases using a - * color table. + * This function is called when an instance ceases using a color table. * * Results: * None. * * Side effects: - * If no other instances are using this color table, a when-idle - * handler is registered to free up the color table and the colors - * allocated for it. + * If no other instances are using this color table, a when-idle handler + * is registered to free up the color table and the colors allocated for + * it. * *---------------------------------------------------------------------- */ static void -FreeColorTable(colorPtr, force) - ColorTable *colorPtr; /* Pointer to the color table which is - * no longer required by an instance. */ - int force; /* Force free to happen immediately. */ +FreeColorTable( + ColorTable *colorPtr, /* Pointer to the color table which is no + * longer required by an instance. */ + int force) /* Force free to happen immediately. */ { colorPtr->refCount--; if (colorPtr->refCount > 0) { return; } + if (force) { if ((colorPtr->flags & DISPOSE_PENDING) != 0) { Tcl_CancelIdleCall(DisposeColorTable, (ClientData) colorPtr); @@ -3551,24 +3537,24 @@ FreeColorTable(colorPtr, force) * * AllocateColors -- * - * This procedure allocates the colors required by a color table, - * and sets up the fields in the color table data structure which - * are used in dithering. + * This function allocates the colors required by a color table, and sets + * up the fields in the color table data structure which are used in + * dithering. * * Results: * None. * * Side effects: - * Colors are allocated from the X server. Fields in the - * color table data structure are updated. + * Colors are allocated from the X server. Fields in the color table data + * structure are updated. * *---------------------------------------------------------------------- */ static void -AllocateColors(colorPtr) - ColorTable *colorPtr; /* Pointer to the color table requiring - * colors to be allocated. */ +AllocateColors( + ColorTable *colorPtr) /* Pointer to the color table requiring colors + * to be allocated. */ { int i, r, g, b, rMult, mono; int numColors, nRed, nGreen, nBlue; @@ -3576,11 +3562,13 @@ AllocateColors(colorPtr) XColor *colors; unsigned long *pixels; - /* 16-bit intensity value for i/n of full intensity. */ -# define CFRAC(i, n) ((i) * 65535 / (n)) + /* + * 16-bit intensity value for i/n of full intensity. + */ +#define CFRAC(i, n) ((i) * 65535 / (n)) /* As for CFRAC, but apply exponent of g. */ -# define CGFRAC(i, n, g) ((int)(65535 * pow((double)(i) / (n), (g)))) +#define CGFRAC(i, n, g) ((int)(65535 * pow((double)(i) / (n), (g)))) /* * First parse the palette specification to get the required number of @@ -3592,16 +3580,14 @@ AllocateColors(colorPtr) igam = 1.0 / colorPtr->id.gamma; /* - * Each time around this loop, we reduce the number of colors we're - * trying to allocate until we succeed in allocating all of the colors - * we need. + * Each time around this loop, we reduce the number of colors we're trying + * to allocate until we succeed in allocating all of the colors we need. */ for (;;) { /* - * If we are using 1 bit/pixel, we don't need to allocate - * any colors (we just use the foreground and background - * colors in the GC). + * If we are using 1 bit/pixel, we don't need to allocate any colors + * (we just use the foreground and background colors in the GC). */ if (mono && (nRed <= 2)) { @@ -3610,12 +3596,12 @@ AllocateColors(colorPtr) } /* - * Calculate the RGB coordinates of the colors we want to - * allocate and store them in *colors. + * Calculate the RGB coordinates of the colors we want to allocate and + * store them in *colors. */ if ((colorPtr->visualInfo.class == DirectColor) - || (colorPtr->visualInfo.class == TrueColor)) { + || (colorPtr->visualInfo.class == TrueColor)) { /* * Direct/True Color: allocate shades of red, green, blue @@ -3642,8 +3628,8 @@ AllocateColors(colorPtr) } } else { /* - * PseudoColor, StaticColor, GrayScale or StaticGray visual: - * we have to allocate each color in the color cube separately. + * PseudoColor, StaticColor, GrayScale or StaticGray visual: we + * have to allocate each color in the color cube separately. */ numColors = (mono) ? nRed: (nRed * nGreen * nBlue); @@ -3695,7 +3681,6 @@ AllocateColors(colorPtr) for (i = 0; i < numColors; ++i) { if (!XAllocColor(colorPtr->id.display, colorPtr->id.colormap, &colors[i])) { - /* * Can't get all the colors we want in the default colormap; * first try freeing colors from other unused color tables. @@ -3707,6 +3692,7 @@ AllocateColors(colorPtr) /* * Still can't allocate the color. */ + break; } } @@ -3714,9 +3700,8 @@ AllocateColors(colorPtr) } /* - * If we didn't get all of the colors, reduce the - * resolution of the color cube, free the ones we got, - * and try again. + * If we didn't get all of the colors, reduce the resolution of the + * color cube, free the ones we got, and try again. */ if (i >= numColors) { @@ -3735,10 +3720,10 @@ AllocateColors(colorPtr) mono = 1; } else { /* - * Reduce the number of shades of each primary to about - * 3/4 of the previous value. This should reduce the - * total number of colors required to about half the - * previous value for PseudoColor displays. + * Reduce the number of shades of each primary to about 3/4 of + * the previous value. This should reduce the total number of + * colors required to about half the previous value for + * PseudoColor displays. */ nRed = (nRed * 3 + 2) / 4; @@ -3753,23 +3738,22 @@ AllocateColors(colorPtr) nRed = nRed / 2; } } - + /* - * We have allocated all of the necessary colors: - * fill in various fields of the ColorTable record. + * We have allocated all of the necessary colors: fill in various fields + * of the ColorTable record. */ if (!mono) { colorPtr->flags |= COLOR_WINDOW; /* - * The following is a hairy hack. We only want to index into - * the pixelMap on colormap displays. However, if the display - * is on Windows, then we actually want to store the index not - * the value since we will be passing the color table into the - * TkPutImage call. + * The following is a hairy hack. We only want to index into the + * pixelMap on colormap displays. However, if the display is on + * Windows, then we actually want to store the index not the value + * since we will be passing the color table into the TkPutImage call. */ - + #ifndef __WIN32__ if ((colorPtr->visualInfo.class != DirectColor) && (colorPtr->visualInfo.class != TrueColor)) { @@ -3784,6 +3768,7 @@ AllocateColors(colorPtr) /* * Set up quantization tables for dithering. */ + rMult = nGreen * nBlue; for (i = 0; i < 256; ++i) { r = (i * (nRed - 1) + 127) / 255; @@ -3799,12 +3784,12 @@ AllocateColors(colorPtr) b = (i * (nBlue - 1) + 127) / 255; if ((colorPtr->visualInfo.class == DirectColor) || (colorPtr->visualInfo.class == TrueColor)) { - colorPtr->redValues[i] = colors[r].pixel - & colorPtr->visualInfo.red_mask; - colorPtr->greenValues[i] = colors[g].pixel - & colorPtr->visualInfo.green_mask; - colorPtr->blueValues[i] = colors[b].pixel - & colorPtr->visualInfo.blue_mask; + colorPtr->redValues[i] = + colors[r].pixel & colorPtr->visualInfo.red_mask; + colorPtr->greenValues[i] = + colors[g].pixel & colorPtr->visualInfo.green_mask; + colorPtr->blueValues[i] = + colors[b].pixel & colorPtr->visualInfo.blue_mask; } else { r *= rMult; g *= nBlue; @@ -3834,27 +3819,27 @@ AllocateColors(colorPtr) * * DisposeColorTable -- * + * Release a color table and its associated resources. * * Results: * None. * * Side effects: - * The colors in the argument color table are freed, as is the - * color table structure itself. The color table is removed - * from the hash table which is used to locate color tables. + * The colors in the argument color table are freed, as is the color + * table structure itself. The color table is removed from the hash table + * which is used to locate color tables. * *---------------------------------------------------------------------- */ static void -DisposeColorTable(clientData) - ClientData clientData; /* Pointer to the ColorTable whose +DisposeColorTable( + ClientData clientData) /* Pointer to the ColorTable whose * colors are to be released. */ { - ColorTable *colorPtr; + ColorTable *colorPtr = (ColorTable *) clientData; Tcl_HashEntry *entry; - colorPtr = (ColorTable *) clientData; if (colorPtr->pixelMap != NULL) { if (colorPtr->numColors > 0) { XFreeColors(colorPtr->id.display, colorPtr->id.colormap, @@ -3866,7 +3851,7 @@ DisposeColorTable(clientData) entry = Tcl_FindHashEntry(&imgPhotoColorHash, (char *) &colorPtr->id); if (entry == NULL) { - panic("DisposeColorTable couldn't find hash entry"); + Tcl_Panic("DisposeColorTable couldn't find hash entry"); } Tcl_DeleteHashEntry(entry); @@ -3878,48 +3863,46 @@ DisposeColorTable(clientData) * * ReclaimColors -- * - * This procedure is called to try to free up colors in the - * colormap used by a color table. It looks for other color - * tables with the same colormap and with a zero live reference - * count, and frees their colors. It only does so if there is - * the possibility of freeing up at least `numColors' colors. + * This function is called to try to free up colors in the colormap used + * by a color table. It looks for other color tables with the same + * colormap and with a zero live reference count, and frees their colors. + * It only does so if there is the possibility of freeing up at least + * `numColors' colors. * * Results: - * The return value is TRUE if any colors were freed, FALSE - * otherwise. + * The return value is TRUE if any colors were freed, FALSE otherwise. * * Side effects: - * ColorTables which are not currently in use may lose their - * color allocations. + * ColorTables which are not currently in use may lose their color + * allocations. * - *---------------------------------------------------------------------- */ + *---------------------------------------------------------------------- + */ static int -ReclaimColors(id, numColors) - ColorTableId *id; /* Pointer to information identifying +ReclaimColors( + ColorTableId *id, /* Pointer to information identifying * the color table which needs more colors. */ - int numColors; /* Number of colors required. */ + int numColors) /* Number of colors required. */ { Tcl_HashSearch srch; Tcl_HashEntry *entry; ColorTable *colorPtr; - int nAvail; + int nAvail = 0; /* - * First scan through the color hash table to get an - * upper bound on how many colors we might be able to free. + * First scan through the color hash table to get an upper bound on how + * many colors we might be able to free. */ - nAvail = 0; entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch); while (entry != NULL) { colorPtr = (ColorTable *) Tcl_GetHashValue(entry); if ((colorPtr->id.display == id->display) - && (colorPtr->id.colormap == id->colormap) - && (colorPtr->liveRefCount == 0 )&& (colorPtr->numColors != 0) - && ((colorPtr->id.palette != id->palette) - || (colorPtr->id.gamma != id->gamma))) { - + && (colorPtr->id.colormap == id->colormap) + && (colorPtr->liveRefCount == 0 )&& (colorPtr->numColors != 0) + && ((colorPtr->id.palette != id->palette) + || (colorPtr->id.gamma != id->gamma))) { /* * We could take this guy's colors off him. */ @@ -3948,8 +3931,7 @@ ReclaimColors(id, numColors) && (colorPtr->id.colormap == id->colormap) && (colorPtr->liveRefCount == 0) && (colorPtr->numColors != 0) && ((colorPtr->id.palette != id->palette) - || (colorPtr->id.gamma != id->gamma))) { - + || (colorPtr->id.gamma != id->gamma))) { /* * Free the colors that this ColorTable has. */ @@ -3964,7 +3946,7 @@ ReclaimColors(id, numColors) entry = Tcl_NextHashEntry(&srch); } - return 1; /* we freed some colors */ + return 1; /* We freed some colors. */ } /* @@ -3972,23 +3954,22 @@ ReclaimColors(id, numColors) * * DisposeInstance -- * - * This procedure is called to finally free up an instance - * of a photo image which is no longer required. + * This function is called to finally free up an instance of a photo + * image which is no longer required. * * Results: * None. * * Side effects: - * The instance data structure and the resources it references - * are freed. + * The instance data structure and the resources it references are freed. * *---------------------------------------------------------------------- */ static void -DisposeInstance(clientData) - ClientData clientData; /* Pointer to the instance whose resources - * are to be released. */ +DisposeInstance( + ClientData clientData) /* Pointer to the instance whose resources are + * to be released. */ { PhotoInstance *instancePtr = (PhotoInstance *) clientData; PhotoInstance *prevPtr; @@ -4014,7 +3995,7 @@ DisposeInstance(clientData) } else { for (prevPtr = instancePtr->masterPtr->instancePtr; prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) { - /* Empty loop body */ + /* Empty loop body. */ } prevPtr->nextPtr = instancePtr->nextPtr; } @@ -4027,16 +4008,16 @@ DisposeInstance(clientData) * * MatchFileFormat -- * - * This procedure is called to find a photo image file format - * handler which can parse the image data in the given file. - * If a user-specified format string is provided, only handlers - * whose names match a prefix of the format string are tried. + * This function is called to find a photo image file format handler + * which can parse the image data in the given file. If a user-specified + * format string is provided, only handlers whose names match a prefix of + * the format string are tried. * * Results: - * A standard TCL return value. If the return value is TCL_OK, a - * pointer to the image format record is returned in - * *imageFormatPtr, and the width and height of the image are - * returned in *widthPtr and *heightPtr. + * A standard TCL return value. If the return value is TCL_OK, a pointer + * to the image format record is returned in *imageFormatPtr, and the + * width and height of the image are returned in *widthPtr and + * *heightPtr. * * Side effects: * None. @@ -4045,24 +4026,23 @@ DisposeInstance(clientData) */ static int -MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, - widthPtr, heightPtr, oldformat) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Channel chan; /* The image file, open for reading. */ - char *fileName; /* The name of the image file. */ - Tcl_Obj *formatObj; /* User-specified format string, or NULL. */ - Tk_PhotoImageFormat **imageFormatPtr; - /* A pointer to the photo image format - * record is returned here. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ - int *oldformat; +MatchFileFormat( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Channel chan, /* The image file, open for reading. */ + char *fileName, /* The name of the image file. */ + Tcl_Obj *formatObj, /* User-specified format string, or NULL. */ + Tk_PhotoImageFormat **imageFormatPtr, + /* A pointer to the photo image format record + * is returned here. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here. */ + int *oldformat) /* Returns 1 if the old image API is used. */ { - int matched; - int useoldformat = 0; + int matched = 0, useoldformat = 0; Tk_PhotoImageFormat *formatPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); char *formatString = NULL; if (formatObj) { @@ -4070,13 +4050,12 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, } /* - * Scan through the table of file format handlers to find - * one which can handle the image. + * Scan through the table of file format handlers to find one which can + * handle the image. */ - matched = 0; for (formatPtr = tsdPtr->formatList; formatPtr != NULL; - formatPtr = formatPtr->nextPtr) { + formatPtr = formatPtr->nextPtr) { if (formatObj != NULL) { if (strncasecmp(formatString, formatPtr->name, strlen(formatPtr->name)) != 0) { @@ -4085,13 +4064,13 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, matched = 1; if (formatPtr->fileMatchProc == NULL) { Tcl_AppendResult(interp, "-file option isn't supported for ", - formatString, " images", (char *) NULL); + formatString, " images", NULL); return TCL_ERROR; } } if (formatPtr->fileMatchProc != NULL) { (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET); - + if ((*formatPtr->fileMatchProc)(chan, fileName, formatObj, widthPtr, heightPtr, interp)) { if (*widthPtr < 1) { @@ -4116,7 +4095,7 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, matched = 1; if (formatPtr->fileMatchProc == NULL) { Tcl_AppendResult(interp, "-file option isn't supported", - " for ", formatString, " images", (char *) NULL); + " for ", formatString, " images", NULL); return TCL_ERROR; } } @@ -4138,13 +4117,12 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, if (formatPtr == NULL) { if ((formatObj != NULL) && !matched) { - Tcl_AppendResult(interp, "image file format \"", - formatString, - "\" is not supported", (char *) NULL); + Tcl_AppendResult(interp, "image file format \"", formatString, + "\" is not supported", NULL); } else { Tcl_AppendResult(interp, - "couldn't recognize data in image file \"", - fileName, "\"", (char *) NULL); + "couldn't recognize data in image file \"", fileName, "\"", + NULL); } return TCL_ERROR; } @@ -4160,16 +4138,16 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, * * MatchStringFormat -- * - * This procedure is called to find a photo image file format - * handler which can parse the image data in the given string. - * If a user-specified format string is provided, only handlers - * whose names match a prefix of the format string are tried. + * This function is called to find a photo image file format handler + * which can parse the image data in the given string. If a + * user-specified format string is provided, only handlers whose names + * match a prefix of the format string are tried. * * Results: - * A standard TCL return value. If the return value is TCL_OK, a - * pointer to the image format record is returned in - * *imageFormatPtr, and the width and height of the image are - * returned in *widthPtr and *heightPtr. + * A standard TCL return value. If the return value is TCL_OK, a pointer + * to the image format record is returned in *imageFormatPtr, and the + * width and height of the image are returned in *widthPtr and + * *heightPtr. * * Side effects: * None. @@ -4178,35 +4156,33 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, */ static int -MatchStringFormat(interp, data, formatObj, imageFormatPtr, - widthPtr, heightPtr, oldformat) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Obj *data; /* Object containing the image data. */ - Tcl_Obj *formatObj; /* User-specified format string, or NULL. */ - Tk_PhotoImageFormat **imageFormatPtr; - /* A pointer to the photo image format - * record is returned here. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ - int *oldformat; /* returns 1 if the old image API is used */ +MatchStringFormat( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Obj *data, /* Object containing the image data. */ + Tcl_Obj *formatObj, /* User-specified format string, or NULL. */ + Tk_PhotoImageFormat **imageFormatPtr, + /* A pointer to the photo image format record + * is returned here. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here. */ + int *oldformat) /* Returns 1 if the old image API is used. */ { - int matched; - int useoldformat = 0; + int matched = 0, useoldformat = 0; Tk_PhotoImageFormat *formatPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); char *formatString = NULL; - + if (formatObj) { formatString = Tcl_GetString(formatObj); } /* - * Scan through the table of file format handlers to find - * one which can handle the image. + * Scan through the table of file format handlers to find one which can + * handle the image. */ - matched = 0; for (formatPtr = tsdPtr->formatList; formatPtr != NULL; formatPtr = formatPtr->nextPtr) { if (formatObj != NULL) { @@ -4217,7 +4193,7 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, matched = 1; if (formatPtr->stringMatchProc == NULL) { Tcl_AppendResult(interp, "-data option isn't supported for ", - formatString, " images", (char *) NULL); + formatString, " images", NULL); return TCL_ERROR; } } @@ -4241,7 +4217,7 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, matched = 1; if (formatPtr->stringMatchProc == NULL) { Tcl_AppendResult(interp, "-data option isn't supported", - " for ", formatString, " images", (char *) NULL); + " for ", formatString, " images", NULL); return TCL_ERROR; } } @@ -4258,10 +4234,9 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, if (formatPtr == NULL) { if ((formatObj != NULL) && !matched) { Tcl_AppendResult(interp, "image format \"", formatString, - "\" is not supported", (char *) NULL); + "\" is not supported", NULL); } else { - Tcl_AppendResult(interp, "couldn't recognize image data", - (char *) NULL); + Tcl_AppendResult(interp, "couldn't recognize image data", NULL); } return TCL_ERROR; } @@ -4276,14 +4251,14 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, * * Tk_FindPhoto -- * - * This procedure is called to get an opaque handle (actually a - * PhotoMaster *) for a given image, which can be used in - * subsequent calls to Tk_PhotoPutBlock, etc. The `name' - * parameter is the name of the image. + * This function is called to get an opaque handle (actually a + * PhotoMaster *) for a given image, which can be used in subsequent + * calls to Tk_PhotoPutBlock, etc. The `name' parameter is the name of + * the image. * * Results: - * The handle for the photo image, or NULL if there is no - * photo image with the name given. + * The handle for the photo image, or NULL if there is no photo image + * with the name given. * * Side effects: * None. @@ -4292,16 +4267,16 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, */ Tk_PhotoHandle -Tk_FindPhoto(interp, imageName) - Tcl_Interp *interp; /* Interpreter (application) in which image +Tk_FindPhoto( + Tcl_Interp *interp, /* Interpreter (application) in which image * exists. */ - CONST char *imageName; /* Name of the desired photo image. */ + CONST char *imageName) /* Name of the desired photo image. */ { ClientData clientData; Tk_ImageType *typePtr; clientData = Tk_GetImageMasterData(interp, imageName, &typePtr); - if (typePtr != &tkPhotoImageType) { + if ((typePtr == NULL) || (typePtr->name != tkPhotoImageType.name)) { return NULL; } return (Tk_PhotoHandle) clientData; @@ -4312,39 +4287,40 @@ Tk_FindPhoto(interp, imageName) * * Tk_PhotoPutBlock -- * - * This procedure is called to put image data into a photo image. + * This function is called to put image data into a photo image. * * Results: - * None. + * A standard Tcl result code. * * Side effects: - * The image data is stored. The image may be expanded. - * The Tk image code is informed that the image has changed. + * The image data is stored. The image may be expanded. The Tk image code + * is informed that the image has changed. If the result code is + * TCL_ERROR, an error message will be placed in the interpreter (if + * non-NULL). * - *---------------------------------------------------------------------- */ + *---------------------------------------------------------------------- + */ -void -Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) - Tk_PhotoHandle handle; /* Opaque handle for the photo image - * to be updated. */ - register Tk_PhotoImageBlock *blockPtr; - /* Pointer to a structure describing the - * pixel data to be copied into the image. */ - int x, y; /* Coordinates of the top-left pixel to - * be updated in the image. */ - int width, height; /* Dimensions of the area of the image - * to be updated. */ - int compRule; /* Compositing rule to use when processing +int +Tk_PhotoPutBlock( + Tcl_Interp *interp, /* Interpreter for passing back error + * messages, or NULL. */ + Tk_PhotoHandle handle, /* Opaque handle for the photo image to be + * updated. */ + register Tk_PhotoImageBlock *blockPtr, + /* Pointer to a structure describing the pixel + * data to be copied into the image. */ + int x, int y, /* Coordinates of the top-left pixel to be + * updated in the image. */ + int width, int height, /* Dimensions of the area of the image to be + * updated. */ + int compRule) /* Compositing rule to use when processing * transparent pixels. */ { register PhotoMaster *masterPtr; - int xEnd, yEnd; - int greenOffset, blueOffset, alphaOffset; - int wLeft, hLeft; - int wCopy, hCopy; - unsigned char *srcPtr, *srcLinePtr; - unsigned char *destPtr, *destLinePtr; - int pitch; + int xEnd, yEnd, greenOffset, blueOffset, alphaOffset; + int wLeft, hLeft, wCopy, hCopy, pitch; + unsigned char *srcPtr, *srcLinePtr, *destPtr, *destLinePtr; int sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO; XRectangle rect; @@ -4359,16 +4335,21 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) height = masterPtr->userHeight - y; } if ((width <= 0) || (height <= 0)) { - return; + return TCL_OK; } xEnd = x + width; yEnd = y + height; if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) { int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32); + if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width), MAX(yEnd, masterPtr->height)) == TCL_ERROR) { - panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + if (interp != NULL) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); + } + return TCL_ERROR; } if (sameSrc) { blockPtr->pixelPtr = masterPtr->pix32; @@ -4376,12 +4357,12 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) } } - if ((y < masterPtr->ditherY) || ((y == masterPtr->ditherY) && (x < masterPtr->ditherX))) { /* * The dithering isn't correct past the start of this block. */ + masterPtr->ditherX = x; masterPtr->ditherY = y; } @@ -4405,111 +4386,162 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) } /* - * Copy the data into our local 32-bit/pixel array. - * If we can do it with a single memcpy, we do. + * Copy the data into our local 32-bit/pixel array. If we can do it with a + * single memcpy, we do. */ destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; pitch = masterPtr->width * 4; /* - * This test is probably too restrictive. We should also be able to - * do a memcpy if pixelSize == 3 and alphaOffset == 0. Maybe other cases - * too. + * Test to see if we can do the whole write in a single copy. This test is + * probably too restrictive. We should also be able to do a memcpy if + * pixelSize == 3 and alphaOffset == 0. Maybe other cases too. */ + if ((blockPtr->pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3) && (width <= blockPtr->width) && (height <= blockPtr->height) && ((height == 1) || ((x == 0) && (width == masterPtr->width) && (blockPtr->pitch == pitch))) && (compRule == TK_PHOTO_COMPOSITE_SET)) { - memcpy((VOID *) destLinePtr, - (VOID *) (blockPtr->pixelPtr + blockPtr->offset[0]), + memcpy(destLinePtr, blockPtr->pixelPtr + blockPtr->offset[0], (size_t) (height * width * 4)); - } else { - int alpha; - for (hLeft = height; hLeft > 0;) { - srcLinePtr = blockPtr->pixelPtr + blockPtr->offset[0]; - hCopy = MIN(hLeft, blockPtr->height); - hLeft -= hCopy; - for (; hCopy > 0; --hCopy) { - if ((blockPtr->pixelSize == 4) && (greenOffset == 1) + + /* + * We know there's an alpha offset and we're setting the data, so skip + * directly to the point when we recompute the photo validity region. + */ + + goto recalculateValidRegion; + } + + /* + * Copy and merge pixels according to the compositing rule. + */ + + for (hLeft = height; hLeft > 0;) { + int pixelSize = blockPtr->pixelSize; + int compRuleSet = (compRule == TK_PHOTO_COMPOSITE_SET); + + srcLinePtr = blockPtr->pixelPtr + blockPtr->offset[0]; + hCopy = MIN(hLeft, blockPtr->height); + hLeft -= hCopy; + for (; hCopy > 0; --hCopy) { + /* + * If the layout of the source line matches our memory layout and + * we're setting, we can just copy the bytes directly, which is + * much faster. + */ + + if ((pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3) && (width <= blockPtr->width) - && (compRule == TK_PHOTO_COMPOSITE_SET)) { - memcpy((VOID *) destLinePtr, (VOID *) srcLinePtr, - (size_t) (width * 4)); - } else { - destPtr = destLinePtr; - for (wLeft = width; wLeft > 0;) { - wCopy = MIN(wLeft, blockPtr->width); - wLeft -= wCopy; - srcPtr = srcLinePtr; - for (; wCopy > 0; --wCopy) { - alpha = srcPtr[alphaOffset]; - - /* - * In the easy case, we can just copy. - */ - if (!alphaOffset || (alpha == 255)) { - /* new solid part of the image */ - *destPtr++ = srcPtr[0]; - *destPtr++ = srcPtr[greenOffset]; - *destPtr++ = srcPtr[blueOffset]; - *destPtr++ = 255; - srcPtr += blockPtr->pixelSize; - continue; - } + && compRuleSet) { + memcpy(destLinePtr, srcLinePtr, (size_t) (width * 4)); + srcLinePtr += blockPtr->pitch; + destLinePtr += pitch; + continue; + } - /* - * Combine according to the compositing rule. - */ - switch (compRule) { - case TK_PHOTO_COMPOSITE_OVERLAY: - if (!destPtr[3]) { - /* - * The destination is entirely - * blank, so set it to the source, - * just as if we used the SET - * compositing rule. - */ - case TK_PHOTO_COMPOSITE_SET: - *destPtr++ = srcPtr[0]; - *destPtr++ = srcPtr[greenOffset]; - *destPtr++ = srcPtr[blueOffset]; - *destPtr++ = alpha; - break; - } + /* + * Have to copy the slow way. + */ + + destPtr = destLinePtr; + for (wLeft = width; wLeft > 0;) { + wCopy = MIN(wLeft, blockPtr->width); + wLeft -= wCopy; + srcPtr = srcLinePtr; - if (alpha) { - int Alpha = destPtr[3]; + /* + * But we might be lucky and be able to use fairly fast loops. + * It's worth checking... + */ - /* - * This implements the Porter-Duff - * Source-Over compositing rule. - */ + if (alphaOffset == 0) { + /* + * This is the non-alpha case, so can still be fairly + * fast. Note that in the non-alpha-source case, the + * compositing rule doesn't apply. + */ - destPtr[0] = PD_SRC_OVER(srcPtr[0],alpha,destPtr[0],Alpha); - destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha,destPtr[1],Alpha); - destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset],alpha,destPtr[2],Alpha); - destPtr[3] = PD_SRC_OVER_ALPHA(alpha,Alpha); - } - /* - * else should be empty space - */ - destPtr += 4; - break; - - default: - panic("unknown compositing rule: %d", compRule); - } - srcPtr += blockPtr->pixelSize; - } + for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) { + *destPtr++ = srcPtr[0]; + *destPtr++ = srcPtr[greenOffset]; + *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = 255; + } + continue; + } else if (compRuleSet) { + /* + * This is the SET compositing rule, which just replaces + * what was there before with the new data. This is + * another fairly fast case. No point in doing a memcpy(); + * the order of channels is probably wrong. + */ + + for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) { + *destPtr++ = srcPtr[0]; + *destPtr++ = srcPtr[greenOffset]; + *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = srcPtr[alphaOffset]; } + continue; + } + + /* + * Bother; need to consider the alpha value of each pixel to + * know what to do. + */ + + for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) { + int alpha = srcPtr[alphaOffset]; + + if (alpha == 255 || !destPtr[3]) { + /* + * Either the source is 100% opaque, or the + * destination is entirely blank. In all cases, we + * just set the destination to the source. + */ + + *destPtr++ = srcPtr[0]; + *destPtr++ = srcPtr[greenOffset]; + *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = alpha; + continue; + } + + /* + * Can still skip doing work if the source is 100% + * transparent at this point. + */ + + if (alpha) { + int Alpha = destPtr[3]; + + /* + * OK, there's real work to be done. Luckily, there's + * a substantial literature on what to do in this + * case. In particular, Porter and Duff have done a + * taxonomy of compositing rules, and the right one is + * the "Source Over" rule. This code implements that. + */ + + destPtr[0] = PD_SRC_OVER(srcPtr[0], alpha, destPtr[0], + Alpha); + destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset], alpha, + destPtr[1], Alpha); + destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset], alpha, + destPtr[2], Alpha); + destPtr[3] = PD_SRC_OVER_ALPHA(alpha, Alpha); + } + + destPtr += 4; } - srcLinePtr += blockPtr->pitch; - destLinePtr += pitch; } + srcLinePtr += blockPtr->pitch; + destLinePtr += pitch; } } @@ -4518,34 +4550,35 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) */ if (alphaOffset) { - int x1, y1, end; - /* - * This block is grossly inefficient. For each row in the image, it + * This block is grossly inefficient. For each row in the image, it * finds each continguous string of nontransparent pixels, then marks - * those areas as valid in the validRegion mask. This makes drawing + * those areas as valid in the validRegion mask. This makes drawing * very efficient, because of the way we use X: we just say, here's - * your mask, and here's your data. We need not worry about the - * current background color, etc. But this costs us a lot on the - * image setup. Still, image setup only happens once, whereas the - * drawing happens many times, so this might be the best way to go. + * your mask, and here's your data. We need not worry about the + * current background color, etc. But this costs us a lot on the image + * setup. Still, image setup only happens once, whereas the drawing + * happens many times, so this might be the best way to go. * * An alternative might be to not set up this mask, and instead, at * drawing time, for each transparent pixel, set its color to the - * color of the background behind that pixel. This is what I suspect - * most of programs do. However, they don't have to deal with the + * color of the background behind that pixel. This is what I suspect + * most of programs do. However, they don't have to deal with the * canvas, which could have many different background colors. * Determining the correct bg color for a given pixel might be * expensive. */ if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) { + TkRegion workRgn; + /* - * Don't need this when using the OVERLAY compositing rule, - * which always strictly increases the valid region. + * Don't need this when using the OVERLAY compositing rule, which + * always strictly increases the valid region. */ - TkRegion workRgn = TkCreateRegion(); + recalculateValidRegion: + workRgn = TkCreateRegion(); rect.x = x; rect.y = y; rect.width = width; @@ -4556,34 +4589,15 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) TkDestroyRegion(workRgn); } - destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3; - for (y1 = 0; y1 < height; y1++) { - x1 = 0; - destPtr = destLinePtr; - while (x1 < width) { - /* search for first non-transparent pixel */ - while ((x1 < width) && !*destPtr) { - x1++; - destPtr += 4; - } - end = x1; - /* search for first transparent pixel */ - while ((end < width) && *destPtr) { - end++; - destPtr += 4; - } - if (end > x1) { - rect.x = x + x1; - rect.y = y + y1; - rect.width = end - x1; - rect.height = 1; - TkUnionRectWithRegion(&rect, masterPtr->validRegion, - masterPtr->validRegion); - } - x1 = end; - } - destLinePtr += masterPtr->width * 4; - } + /* + * Factorize out the main part of the building of the region data to + * allow for more efficient per-platform implementations. [Bug 919066] + */ + + TkpBuildRegionFromAlphaData(masterPtr->validRegion, (unsigned) x, + (unsigned) y, (unsigned) width, (unsigned) height, + masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3, + 4, (unsigned) masterPtr->width * 4); } else { rect.x = x; rect.y = y; @@ -4603,6 +4617,7 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) * builds up large simple-alpha images by single pixels. We don't * negate COMPLEX_ALPHA in this case. [Bug 1409140] */ + if (!(masterPtr->flags & COMPLEX_ALPHA)) { unsigned char newAlpha; @@ -4620,6 +4635,7 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) * Toggle to only checking the changed pixels requires knowing where * the alpha pixels are. */ + ToggleComplexAlphaIfNeeded(masterPtr); } @@ -4633,8 +4649,9 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) * Tell the core image code that this image has changed. */ - Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width, - masterPtr->height); + Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, + masterPtr->width, masterPtr->height); + return TCL_OK; } /* @@ -4642,60 +4659,56 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) * * Tk_PhotoPutZoomedBlock -- * - * This procedure is called to put image data into a photo image, - * with possible subsampling and/or zooming of the pixels. + * This function is called to put image data into a photo image, with + * possible subsampling and/or zooming of the pixels. * * Results: * None. * * Side effects: - * The image data is stored. The image may be expanded. - * The Tk image code is informed that the image has changed. + * The image data is stored. The image may be expanded. The Tk image code + * is informed that the image has changed. * *---------------------------------------------------------------------- */ -void -Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, - subsampleX, subsampleY, compRule) - Tk_PhotoHandle handle; /* Opaque handle for the photo image - * to be updated. */ - register Tk_PhotoImageBlock *blockPtr; - /* Pointer to a structure describing the - * pixel data to be copied into the image. */ - int x, y; /* Coordinates of the top-left pixel to - * be updated in the image. */ - int width, height; /* Dimensions of the area of the image - * to be updated. */ - int zoomX, zoomY; /* Zoom factors for the X and Y axes. */ - int subsampleX, subsampleY; /* Subsampling factors for the X and Y axes. */ - int compRule; /* Compositing rule to use when processing +int +Tk_PhotoPutZoomedBlock( + Tcl_Interp *interp, /* Interpreter for passing back error + * messages, or NULL. */ + Tk_PhotoHandle handle, /* Opaque handle for the photo image to be + * updated. */ + register Tk_PhotoImageBlock *blockPtr, + /* Pointer to a structure describing the pixel + * data to be copied into the image. */ + int x, int y, /* Coordinates of the top-left pixel to be + * updated in the image. */ + int width, int height, /* Dimensions of the area of the image to be + * updated. */ + int zoomX, int zoomY, /* Zoom factors for the X and Y axes. */ + int subsampleX, int subsampleY, + /* Subsampling factors for the X and Y + * axes. */ + int compRule) /* Compositing rule to use when processing * transparent pixels. */ { - register PhotoMaster *masterPtr; - int xEnd, yEnd; - int greenOffset, blueOffset, alphaOffset; - int wLeft, hLeft; - int wCopy, hCopy; - int blockWid, blockHt; - unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr; - unsigned char *destPtr, *destLinePtr; - int pitch; - int xRepeat, yRepeat; - int blockXSkip, blockYSkip, sourceIsSimplePhoto; + register PhotoMaster *masterPtr = (PhotoMaster *) handle; + int xEnd, yEnd, greenOffset, blueOffset, alphaOffset; + int wLeft, hLeft, wCopy, hCopy, blockWid, blockHt; + unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr, *destPtr, *destLinePtr; + int pitch, xRepeat, yRepeat, blockXSkip, blockYSkip, sourceIsSimplePhoto; XRectangle rect; if (zoomX==1 && zoomY==1 && subsampleX==1 && subsampleY==1) { - Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule); - return; + return Tk_PhotoPutBlock(interp, handle, blockPtr, x, y, width, height, + compRule); } sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO; compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO; - masterPtr = (PhotoMaster *) handle; if (zoomX <= 0 || zoomY <= 0) { - return; + return TCL_OK; } if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) { width = masterPtr->userWidth - x; @@ -4705,7 +4718,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, height = masterPtr->userHeight - y; } if (width <= 0 || height <= 0) { - return; + return TCL_OK; } xEnd = x + width; @@ -4714,7 +4727,11 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32); if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width), MAX(yEnd, masterPtr->height)) == TCL_ERROR) { - panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + if (interp != NULL) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); + } + return TCL_ERROR; } if (sameSrc) { blockPtr->pixelPtr = masterPtr->pix32; @@ -4799,10 +4816,12 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, srcPtr = srcLinePtr; for (; wCopy > 0; wCopy -= zoomX) { for (xRepeat = MIN(wCopy, zoomX); xRepeat > 0; xRepeat--) { - int alpha = srcPtr[alphaOffset]; + int alpha = srcPtr[alphaOffset];/* Source alpha. */ + /* * Common case (solid pixels) first */ + if (!alphaOffset || (alpha == 255)) { *destPtr++ = srcPtr[0]; *destPtr++ = srcPtr[greenOffset]; @@ -4811,32 +4830,33 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, continue; } - switch (compRule) { - case TK_PHOTO_COMPOSITE_OVERLAY: - if (!destPtr[3]) { - /* - * The destination is entirely blank, - * so set it to the source, just as if - * we used the SET compositing rule. - */ - case TK_PHOTO_COMPOSITE_SET: - *destPtr++ = srcPtr[0]; - *destPtr++ = srcPtr[greenOffset]; - *destPtr++ = srcPtr[blueOffset]; - *destPtr++ = alpha; - break; - } - if (alpha) { - int Alpha = destPtr[3]; - destPtr[0] = PD_SRC_OVER(srcPtr[0],alpha,destPtr[0],Alpha); - destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha,destPtr[1],Alpha); - destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset],alpha,destPtr[2],Alpha); - destPtr[3] = PD_SRC_OVER_ALPHA(alpha,Alpha); - } + if (compRule==TK_PHOTO_COMPOSITE_SET || !destPtr[3]) { + /* + * Either this is the SET rule (we overwrite + * whatever is there) or the destination is + * entirely blank. In both cases, we just set the + * destination to the source. + */ + + *destPtr++ = srcPtr[0]; + *destPtr++ = srcPtr[greenOffset]; + *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = alpha; + } else if (alpha) { + int Alpha = destPtr[3]; /* Destination + * alpha. */ + + destPtr[0] = PD_SRC_OVER(srcPtr[0], alpha, + destPtr[0], Alpha); + destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha, + destPtr[1], Alpha); + destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset], alpha, + destPtr[2], Alpha); + destPtr[3] = PD_SRC_OVER_ALPHA(alpha, Alpha); + + destPtr += 4; + } else { destPtr += 4; - break; - default: - panic("unknown compositing rule: %d", compRule); } } srcPtr += blockXSkip; @@ -4856,13 +4876,12 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, */ if (alphaOffset) { - int x1, y1, end; - if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) { /* * Don't need this when using the OVERLAY compositing rule, which * always strictly increases the valid region. */ + TkRegion workRgn = TkCreateRegion(); rect.x = x; @@ -4875,34 +4894,10 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, TkDestroyRegion(workRgn); } - destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3; - for (y1 = 0; y1 < height; y1++) { - x1 = 0; - destPtr = destLinePtr; - while (x1 < width) { - /* search for first non-transparent pixel */ - while ((x1 < width) && !*destPtr) { - x1++; - destPtr += 4; - } - end = x1; - /* search for first transparent pixel */ - while ((end < width) && *destPtr) { - end++; - destPtr += 4; - } - if (end > x1) { - rect.x = x + x1; - rect.y = y + y1; - rect.width = end - x1; - rect.height = 1; - TkUnionRectWithRegion(&rect, masterPtr->validRegion, - masterPtr->validRegion); - } - x1 = end; - } - destLinePtr += masterPtr->width * 4; - } + TkpBuildRegionFromAlphaData(masterPtr->validRegion, + (unsigned)x, (unsigned)y, (unsigned)width, (unsigned)height, + &masterPtr->pix32[(y * masterPtr->width + x) * 4 + 3], 4, + (unsigned) masterPtr->width * 4); } else { rect.x = x; rect.y = y; @@ -4946,7 +4941,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, * Update each instance. */ - Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, x, y, width, height); + Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y, width, height); /* * Tell the core image code that this image has changed. @@ -4954,6 +4949,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width, masterPtr->height); + return TCL_OK; } /* @@ -4961,27 +4957,27 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, * * Tk_DitherPhoto -- * - * This procedure is called to update an area of each instance's - * pixmap by dithering the corresponding area of the image master. + * This function is called to update an area of each instance's pixmap by + * dithering the corresponding area of the image master. * * Results: * None. * * Side effects: - * The pixmap of each instance of this image gets updated. - * The fields in *masterPtr indicating which area of the image - * is correctly dithered get updated. + * The pixmap of each instance of this image gets updated. The fields in + * *masterPtr indicating which area of the image is correctly dithered + * get updated. * *---------------------------------------------------------------------- */ void -Tk_DitherPhoto(photo, x, y, width, height) - Tk_PhotoHandle photo; /* Image master whose instances are - * to be updated. */ - int x, y; /* Coordinates of the top-left pixel - * in the area to be dithered. */ - int width, height; /* Dimensions of the area to be dithered. */ +Tk_DitherPhoto( + Tk_PhotoHandle photo, /* Image master whose instances are to be + * updated. */ + int x, int y, /* Coordinates of the top-left pixel in the + * area to be dithered. */ + int width, int height) /* Dimensions of the area to be dithered. */ { PhotoMaster *masterPtr = (PhotoMaster *) photo; PhotoInstance *instancePtr; @@ -4996,14 +4992,13 @@ Tk_DitherPhoto(photo, x, y, width, height) } /* - * Work out whether this block will be correctly dithered - * and whether it will extend the correctly dithered region. + * Work out whether this block will be correctly dithered and whether it + * will extend the correctly dithered region. */ if (((y < masterPtr->ditherY) || ((y == masterPtr->ditherY) && (x <= masterPtr->ditherX))) && ((y + height) > (masterPtr->ditherY))) { - /* * This block starts inside (or immediately after) the correctly * dithered region, so the first scan line at least will be right. @@ -5012,8 +5007,8 @@ Tk_DitherPhoto(photo, x, y, width, height) if ((x == 0) && (width == masterPtr->width)) { /* - * We are doing the full width, therefore the dithering - * will be correct to the end. + * We are doing the full width, therefore the dithering will be + * correct to the end. */ masterPtr->ditherX = 0; @@ -5021,8 +5016,8 @@ Tk_DitherPhoto(photo, x, y, width, height) } else { /* * We are doing partial scanlines, therefore the - * correctly-dithered region will be extended by - * at most one scan line. + * correctly-dithered region will be extended by at most one scan + * line. */ if (x <= masterPtr->ditherX) { @@ -5034,16 +5029,15 @@ Tk_DitherPhoto(photo, x, y, width, height) } } } - -} +} /* *---------------------------------------------------------------------- * * DitherInstance -- * - * This procedure is called to update an area of an instance's - * pixmap by dithering the corresponding area of the master. + * This function is called to update an area of an instance's pixmap by + * dithering the corresponding area of the master. * * Results: * None. @@ -5055,33 +5049,24 @@ Tk_DitherPhoto(photo, x, y, width, height) */ static void -DitherInstance(instancePtr, xStart, yStart, width, height) - PhotoInstance *instancePtr; /* The instance to be updated. */ - int xStart, yStart; /* Coordinates of the top-left pixel in the +DitherInstance( + PhotoInstance *instancePtr, /* The instance to be updated. */ + int xStart, int yStart, /* Coordinates of the top-left pixel in the * block to be dithered. */ - int width, height; /* Dimensions of the block to be dithered. */ + int width, int height) /* Dimensions of the block to be dithered. */ { - PhotoMaster *masterPtr; - ColorTable *colorPtr; + PhotoMaster *masterPtr = instancePtr->masterPtr; + ColorTable *colorPtr = instancePtr->colorTablePtr; XImage *imagePtr; - int nLines, bigEndian; - int i, c, x, y; - int xEnd, yEnd; + int nLines, bigEndian, i, c, x, y, xEnd, doDithering = 1; int bitsPerPixel, bytesPerLine, lineLength; - unsigned char *srcLinePtr, *srcPtr; - schar *errLinePtr, *errPtr; - unsigned char *destBytePtr, *dstLinePtr; - pixel *destLongPtr; + unsigned char *srcLinePtr; + schar *errLinePtr; pixel firstBit, word, mask; - int col[3]; - int doDithering = 1; - - colorPtr = instancePtr->colorTablePtr; - masterPtr = instancePtr->masterPtr; /* - * Turn dithering off in certain cases where it is not - * needed (TrueColor, DirectColor with many colors). + * Turn dithering off in certain cases where it is not needed (TrueColor, + * DirectColor with many colors). */ if ((colorPtr->visualInfo.class == DirectColor) @@ -5097,9 +5082,8 @@ DitherInstance(instancePtr, xStart, yStart, width, height) } /* - * First work out how many lines to do at a time, - * then how many bytes we'll need for pixel storage, - * and allocate it. + * First work out how many lines to do at a time, then how many bytes + * we'll need for pixel storage, and allocate it. */ nLines = (MAX_PIXELS + width - 1) / width; @@ -5112,14 +5096,15 @@ DitherInstance(instancePtr, xStart, yStart, width, height) imagePtr = instancePtr->imagePtr; if (imagePtr == NULL) { - return; /* we must be really tight on memory */ + return; /* We must be really tight on memory. */ } bitsPerPixel = imagePtr->bits_per_pixel; bytesPerLine = ((bitsPerPixel * width + 31) >> 3) & ~3; imagePtr->width = width; imagePtr->height = nLines; imagePtr->bytes_per_line = bytesPerLine; - imagePtr->data = (char *) ckalloc((unsigned) (imagePtr->bytes_per_line * nLines)); + imagePtr->data = (char *) + ckalloc((unsigned) (imagePtr->bytes_per_line * nLines)); bigEndian = imagePtr->bitmap_bit_order == MSBFirst; firstBit = bigEndian? (1 << (imagePtr->bitmap_unit - 1)): 1; @@ -5129,46 +5114,50 @@ DitherInstance(instancePtr, xStart, yStart, width, height) xEnd = xStart + width; /* - * Loop over the image, doing at most nLines lines before - * updating the screen image. + * Loop over the image, doing at most nLines lines before updating the + * screen image. */ for (; height > 0; height -= nLines) { + unsigned char *dstLinePtr = (unsigned char *) imagePtr->data; + int yEnd; + if (nLines > height) { nLines = height; } - dstLinePtr = (unsigned char *) imagePtr->data; yEnd = yStart + nLines; for (y = yStart; y < yEnd; ++y) { - srcPtr = srcLinePtr; - errPtr = errLinePtr; - destBytePtr = dstLinePtr; - destLongPtr = (pixel *) dstLinePtr; + unsigned char *srcPtr = srcLinePtr; + schar *errPtr = errLinePtr; + unsigned char *destBytePtr = dstLinePtr; + pixel *destLongPtr = (pixel *) dstLinePtr; + if (colorPtr->flags & COLOR_WINDOW) { /* - * Color window. We dither the three components - * independently, using Floyd-Steinberg dithering, - * which propagates errors from the quantization of - * pixels to the pixels below and to the right. + * Color window. We dither the three components independently, + * using Floyd-Steinberg dithering, which propagates errors + * from the quantization of pixels to the pixels below and to + * the right. */ for (x = xStart; x < xEnd; ++x) { + int col[3]; + if (doDithering) { for (i = 0; i < 3; ++i) { /* * Compute the error propagated into this pixel - * for this component. - * If e[x,y] is the array of quantization error - * values, we compute + * for this component. If e[x,y] is the array of + * quantization error values, we compute * 7/16 * e[x-1,y] + 1/16 * e[x-1,y-1] * + 5/16 * e[x,y-1] + 3/16 * e[x+1,y-1] * and round it to an integer. * - * The expression ((c + 2056) >> 4) - 128 - * computes round(c / 16), and works correctly on - * machines without a sign-extending right shift. + * The expression ((c + 2056) >> 4) - 128 computes + * round(c / 16), and works correctly on machines + * without a sign-extending right shift. */ - + c = (x > 0) ? errPtr[-3] * 7: 0; if (y > 0) { if (x > 0) { @@ -5179,13 +5168,13 @@ DitherInstance(instancePtr, xStart, yStart, width, height) c += errPtr[-lineLength+3] * 3; } } - + /* * Add the propagated error to the value of this * component, quantize it, and store the * quantization error. */ - + c = ((c + 2056) >> 4) - 128 + *srcPtr++; if (c < 0) { c = 0; @@ -5196,9 +5185,9 @@ DitherInstance(instancePtr, xStart, yStart, width, height) *errPtr++ = c - col[i]; } } else { - /* - * Output is virtually continuous in this case, - * so don't bother dithering. + /* + * Output is virtually continuous in this case, so + * don't bother dithering. */ col[0] = *srcPtr++; @@ -5208,8 +5197,8 @@ DitherInstance(instancePtr, xStart, yStart, width, height) srcPtr++; /* - * Translate the quantized component values into - * an X pixel value, and store it in the image. + * Translate the quantized component values into an X + * pixel value, and store it in the image. */ i = colorPtr->redValues[col[0]] @@ -5219,32 +5208,34 @@ DitherInstance(instancePtr, xStart, yStart, width, height) i = colorPtr->pixelMap[i]; } switch (bitsPerPixel) { - case NBBY: - *destBytePtr++ = i; - break; + case NBBY: + *destBytePtr++ = i; + break; #ifndef __WIN32__ -/* - * This case is not valid for Windows because the image format is different - * from the pixel format in Win32. Eventually we need to fix the image - * code in Tk to use the Windows native image ordering. This would speed - * up the image code for all of the common sizes. - */ + /* + * This case is not valid for Windows because the + * image format is different from the pixel format in + * Win32. Eventually we need to fix the image code in + * Tk to use the Windows native image ordering. This + * would speed up the image code for all of the common + * sizes. + */ - case NBBY * sizeof(pixel): - *destLongPtr++ = i; - break; + case NBBY * sizeof(pixel): + *destLongPtr++ = i; + break; #endif - default: - XPutPixel(imagePtr, x - xStart, y - yStart, - (unsigned) i); + default: + XPutPixel(imagePtr, x - xStart, y - yStart, + (unsigned) i); } } } else if (bitsPerPixel > 1) { /* - * Multibit monochrome window. The operation here is similar + * Multibit monochrome window. The operation here is similar * to the color window case above, except that there is only - * one component. If the master image is in color, use the + * one component. If the master image is in color, use the * luminance computed as * 0.344 * red + 0.5 * green + 0.156 * blue. */ @@ -5266,7 +5257,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) c += srcPtr[0]; } else { c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16 - + srcPtr[2] * 5 + 16) >> 5; + + srcPtr[2] * 5 + 16) >> 5; } srcPtr += 4; @@ -5279,40 +5270,42 @@ DitherInstance(instancePtr, xStart, yStart, width, height) *errPtr++ = c - i; i = colorPtr->redValues[i]; switch (bitsPerPixel) { - case NBBY: - *destBytePtr++ = i; - break; + case NBBY: + *destBytePtr++ = i; + break; #ifndef __WIN32__ -/* - * This case is not valid for Windows because the image format is different - * from the pixel format in Win32. Eventually we need to fix the image - * code in Tk to use the Windows native image ordering. This would speed - * up the image code for all of the common sizes. - */ + /* + * This case is not valid for Windows because the + * image format is different from the pixel format in + * Win32. Eventually we need to fix the image code in + * Tk to use the Windows native image ordering. This + * would speed up the image code for all of the common + * sizes. + */ - case NBBY * sizeof(pixel): - *destLongPtr++ = i; - break; + case NBBY * sizeof(pixel): + *destLongPtr++ = i; + break; #endif - default: - XPutPixel(imagePtr, x - xStart, y - yStart, - (unsigned) i); + default: + XPutPixel(imagePtr, x - xStart, y - yStart, + (unsigned) i); } } } else { /* - * 1-bit monochrome window. This is similar to the - * multibit monochrome case above, except that the - * quantization is simpler (we only have black = 0 - * and white = 255), and we produce an XY-Bitmap. + * 1-bit monochrome window. This is similar to the multibit + * monochrome case above, except that the quantization is + * simpler (we only have black = 0 and white = 255), and we + * produce an XY-Bitmap. */ word = 0; mask = firstBit; for (x = xStart; x < xEnd; ++x) { /* - * If we have accumulated a whole word, store it - * in the image and start a new word. + * If we have accumulated a whole word, store it in the + * image and start a new word. */ if (mask == 0) { @@ -5337,7 +5330,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) c += srcPtr[0]; } else { c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16 - + srcPtr[2] * 5 + 16) >> 5; + + srcPtr[2] * 5 + 16) >> 5; } srcPtr += 4; @@ -5362,8 +5355,8 @@ DitherInstance(instancePtr, xStart, yStart, width, height) } /* - * Update the pixmap for this instance with the block of - * pixels that we have just computed. + * Update the pixmap for this instance with the block of pixels that + * we have just computed. */ TkPutImage(colorPtr->pixelMap, colorPtr->numColors, @@ -5371,7 +5364,6 @@ DitherInstance(instancePtr, xStart, yStart, width, height) instancePtr->gc, imagePtr, 0, 0, xStart, yStart, (unsigned) width, (unsigned) nLines); yStart = yEnd; - } ckfree(imagePtr->data); @@ -5383,26 +5375,25 @@ DitherInstance(instancePtr, xStart, yStart, width, height) * * Tk_PhotoBlank -- * - * This procedure is called to clear an entire photo image. + * This function is called to clear an entire photo image. * * Results: * None. * * Side effects: - * The valid region for the image is set to the null region. - * The generic image code is notified that the image has changed. + * The valid region for the image is set to the null region. The generic + * image code is notified that the image has changed. * *---------------------------------------------------------------------- */ void -Tk_PhotoBlank(handle) - Tk_PhotoHandle handle; /* Handle for the image to be blanked. */ +Tk_PhotoBlank( + Tk_PhotoHandle handle) /* Handle for the image to be blanked. */ { - PhotoMaster *masterPtr; + PhotoMaster *masterPtr = (PhotoMaster *) handle; PhotoInstance *instancePtr; - masterPtr = (PhotoMaster *) handle; masterPtr->ditherX = masterPtr->ditherY = 0; masterPtr->flags = 0; @@ -5416,16 +5407,16 @@ Tk_PhotoBlank(handle) masterPtr->validRegion = TkCreateRegion(); /* - * Clear out the 32-bit pixel storage array. - * Clear out the dithering error arrays for each instance. + * Clear out the 32-bit pixel storage array. Clear out the dithering error + * arrays for each instance. */ - memset((VOID *) masterPtr->pix32, 0, + memset(masterPtr->pix32, 0, (size_t) (masterPtr->width * masterPtr->height * 4)); for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { if (instancePtr->error) { - memset((VOID *) instancePtr->error, 0, + memset(instancePtr->error, 0, (size_t) (masterPtr->width * masterPtr->height * 3 * sizeof(schar))); } @@ -5444,30 +5435,29 @@ Tk_PhotoBlank(handle) * * Tk_PhotoExpand -- * - * This procedure is called to request that a photo image be - * expanded if necessary to be at least `width' pixels wide and - * `height' pixels high. If the user has declared a definite - * image size (using the -width and -height configuration - * options) then this call has no effect. + * This function is called to request that a photo image be expanded if + * necessary to be at least `width' pixels wide and `height' pixels high. + * If the user has declared a definite image size (using the -width and + * -height configuration options) then this call has no effect. * * Results: * None. * * Side effects: - * The size of the photo image may change; if so the generic - * image code is informed. + * The size of the photo image may change; if so the generic image code + * is informed. * *---------------------------------------------------------------------- */ -void -Tk_PhotoExpand(handle, width, height) - Tk_PhotoHandle handle; /* Handle for the image to be expanded. */ - int width, height; /* Desired minimum dimensions of the image. */ +int +Tk_PhotoExpand( + Tcl_Interp *interp, /* Interpreter for passing back error + * messages, or NULL. */ + Tk_PhotoHandle handle, /* Handle for the image to be expanded. */ + int width, int height) /* Desired minimum dimensions of the image. */ { - PhotoMaster *masterPtr; - - masterPtr = (PhotoMaster *) handle; + PhotoMaster *masterPtr = (PhotoMaster *) handle; if (width <= masterPtr->width) { width = masterPtr->width; @@ -5478,11 +5468,16 @@ Tk_PhotoExpand(handle, width, height) if ((width != masterPtr->width) || (height != masterPtr->height)) { if (ImgPhotoSetSize(masterPtr, MAX(width, masterPtr->width), MAX(height, masterPtr->height)) == TCL_ERROR) { - panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + if (interp != NULL) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); + } + return TCL_ERROR; } Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width, masterPtr->height); } + return TCL_OK; } /* @@ -5490,12 +5485,10 @@ Tk_PhotoExpand(handle, width, height) * * Tk_PhotoGetSize -- * - * This procedure is called to obtain the current size of a photo - * image. + * This function is called to obtain the current size of a photo image. * * Results: - * The image's width and height are returned in *widthp - * and *heightp. + * The image's width and height are returned in *widthp and *heightp. * * Side effects: * None. @@ -5504,15 +5497,15 @@ Tk_PhotoExpand(handle, width, height) */ void -Tk_PhotoGetSize(handle, widthPtr, heightPtr) - Tk_PhotoHandle handle; /* Handle for the image whose dimensions - * are requested. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are returned +Tk_PhotoGetSize( + Tk_PhotoHandle handle, /* Handle for the image whose dimensions are + * requested. */ + int *widthPtr, int *heightPtr) + /* The dimensions of the image are returned * here. */ { - PhotoMaster *masterPtr; + PhotoMaster *masterPtr = (PhotoMaster *) handle; - masterPtr = (PhotoMaster *) handle; *widthPtr = masterPtr->width; *heightPtr = masterPtr->height; } @@ -5522,38 +5515,42 @@ Tk_PhotoGetSize(handle, widthPtr, heightPtr) * * Tk_PhotoSetSize -- * - * This procedure is called to set size of a photo image. - * This call is equivalent to using the -width and -height - * configuration options. + * This function is called to set size of a photo image. This call is + * equivalent to using the -width and -height configuration options. * * Results: * None. * * Side effects: - * The size of the image may change; if so the generic - * image code is informed. + * The size of the image may change; if so the generic image code is + * informed. * *---------------------------------------------------------------------- */ -void -Tk_PhotoSetSize(handle, width, height) - Tk_PhotoHandle handle; /* Handle for the image whose size is to - * be set. */ - int width, height; /* New dimensions for the image. */ +int +Tk_PhotoSetSize( + Tcl_Interp *interp, /* Interpreter for passing back error + * messages, or NULL. */ + Tk_PhotoHandle handle, /* Handle for the image whose size is to be + * set. */ + int width, int height) /* New dimensions for the image. */ { - PhotoMaster *masterPtr; - - masterPtr = (PhotoMaster *) handle; + PhotoMaster *masterPtr = (PhotoMaster *) handle; masterPtr->userWidth = width; masterPtr->userHeight = height; if (ImgPhotoSetSize(masterPtr, ((width > 0) ? width: masterPtr->width), ((height > 0) ? height: masterPtr->height)) == TCL_ERROR) { - panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + if (interp != NULL) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); + } + return TCL_ERROR; } Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width, masterPtr->height); + return TCL_OK; } /* @@ -5561,14 +5558,14 @@ Tk_PhotoSetSize(handle, width, height) * * TkGetPhotoValidRegion -- * - * This procedure is called to get the part of the photo where - * there is valid data. Or, conversely, the part of the photo - * which is transparent. + * This function is called to get the part of the photo where there is + * valid data. Or, conversely, the part of the photo which is + * transparent. * * Results: - * A TkRegion value that indicates the current area of the photo - * that is valid. This value should not be used after any - * modification to the photo image. + * A TkRegion value that indicates the current area of the photo that is + * valid. This value should not be used after any modification to the + * photo image. * * Side Effects: * None. @@ -5577,13 +5574,12 @@ Tk_PhotoSetSize(handle, width, height) */ TkRegion -TkPhotoGetValidRegion(handle) - Tk_PhotoHandle handle; /* Handle for the image whose valid region - * is to obtained. */ +TkPhotoGetValidRegion( + Tk_PhotoHandle handle) /* Handle for the image whose valid region is + * to obtained. */ { - PhotoMaster *masterPtr; + PhotoMaster *masterPtr = (PhotoMaster *) handle; - masterPtr = (PhotoMaster *) handle; return masterPtr->validRegion; } @@ -5592,15 +5588,15 @@ TkPhotoGetValidRegion(handle) * * ImgGetPhoto -- * - * This procedure is called to obtain image data from a photo - * image. This procedure fills in the Tk_PhotoImageBlock structure - * pointed to by `blockPtr' with details of the address and - * layout of the image data in memory. + * This function is called to obtain image data from a photo image. This + * function fills in the Tk_PhotoImageBlock structure pointed to by + * `blockPtr' with details of the address and layout of the image data in + * memory. * * Results: - * A pointer to the allocated data which should be freed later. - * NULL if there is no need to free data because - * blockPtr->pixelPtr points directly to the image data. + * A pointer to the allocated data which should be freed later. NULL if + * there is no need to free data because blockPtr->pixelPtr points + * directly to the image data. * * Side effects: * None. @@ -5609,13 +5605,13 @@ TkPhotoGetValidRegion(handle) */ static char * -ImgGetPhoto(masterPtr, blockPtr, optPtr) - PhotoMaster *masterPtr; /* Handle for the photo image from which - * image data is desired. */ - Tk_PhotoImageBlock *blockPtr; - /* Information about the address and layout - * of the image data is returned here. */ - struct SubcommandOptions *optPtr; +ImgGetPhoto( + PhotoMaster *masterPtr, /* Handle for the photo image from which image + * data is desired. */ + Tk_PhotoImageBlock *blockPtr, + /* Information about the address and layout of + * the image data is returned here. */ + struct SubcommandOptions *optPtr) { unsigned char *pixelPtr; int x, y, greenOffset, blueOffset, alphaOffset; @@ -5630,8 +5626,7 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) (!(optPtr->options & OPT_BACKGROUND) || ((optPtr->background->red == optPtr->background->green) && (optPtr->background->red == optPtr->background->blue)))) { - blockPtr->offset[0] = blockPtr->offset[1] = - blockPtr->offset[2]; + blockPtr->offset[0] = blockPtr->offset[1] = blockPtr->offset[2]; } alphaOffset = 0; for (y = 0; y < blockPtr->height; y++) { @@ -5657,13 +5652,14 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; if (((optPtr->options & OPT_BACKGROUND) && alphaOffset) || - ((optPtr->options & OPT_GRAYSCALE) && (greenOffset || blueOffset))) { + ((optPtr->options & OPT_GRAYSCALE) && (greenOffset||blueOffset))) { int newPixelSize,x,y; unsigned char *srcPtr, *destPtr; char *data; - newPixelSize = (!(optPtr->options & OPT_BACKGROUND) && alphaOffset) ? 2 : 1; - if ((greenOffset || blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) { + newPixelSize = (!(optPtr->options & OPT_BACKGROUND) && alphaOffset) + ? 2 : 1; + if ((greenOffset||blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) { newPixelSize += 2; } data = ckalloc((unsigned int) (newPixelSize * @@ -5677,17 +5673,19 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } else if (optPtr->options & OPT_GRAYSCALE) { for (y = blockPtr->height; y > 0; y--) { for (x = blockPtr->width; x > 0; x--) { - *destPtr = (unsigned char) ((srcPtr[0] * 11 + srcPtr[1] * 16 - + srcPtr[2] * 5 + 16) >> 5); + *destPtr = (unsigned char) ((srcPtr[0]*11 + srcPtr[1]*16 + + srcPtr[2]*5 + 16) >> 5); srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } else { for (y = blockPtr->height; y > 0; y--) { @@ -5698,18 +5696,22 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } srcPtr = blockPtr->pixelPtr + alphaOffset; destPtr = (unsigned char *) data; if (!alphaOffset) { - /* nothing to be done */ + /* + * Nothing to be done. + */ } else if (optPtr->options & OPT_BACKGROUND) { if (newPixelSize > 2) { - int red = optPtr->background->red>>8; - int green = optPtr->background->green>>8; - int blue = optPtr->background->blue>>8; + int red = optPtr->background->red>>8; + int green = optPtr->background->green>>8; + int blue = optPtr->background->blue>>8; + for (y = blockPtr->height; y > 0; y--) { for (x = blockPtr->width; x > 0; x--) { destPtr[0] += (unsigned char) (((255 - *srcPtr) * @@ -5721,12 +5723,14 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } else { int gray = (unsigned char) (((optPtr->background->red>>8) * 11 - + (optPtr->background->green>>8) * 16 - + (optPtr->background->blue>>8) * 5 + 16) >> 5); + + (optPtr->background->green>>8) * 16 + + (optPtr->background->blue>>8) * 5 + 16) >> 5); + for (y = blockPtr->height; y > 0; y--) { for (x = blockPtr->width; x > 0; x--) { destPtr[0] += ((255 - *srcPtr) * @@ -5734,7 +5738,8 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } } else { @@ -5745,7 +5750,8 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } blockPtr->pixelPtr = (unsigned char *) data; @@ -5769,8 +5775,8 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) * * ImgStringWrite -- * - * Default string write function. The data is formatted in - * the default format as accepted by the "<img> put" command. + * Default string write function. The data is formatted in the default + * format as accepted by the "<img> put" command. * * Results: * A standard Tcl result. @@ -5782,12 +5788,12 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) */ static int -ImgStringWrite(interp, formatString, blockPtr) - Tcl_Interp *interp; - Tcl_Obj *formatString; - Tk_PhotoImageBlock *blockPtr; +ImgStringWrite( + Tcl_Interp *interp, + Tcl_Obj *formatString, + Tk_PhotoImageBlock *blockPtr) { - int row,col; + int row, col; char *line, *linePtr; unsigned char *pixelPtr; int greenOffset, blueOffset; @@ -5822,14 +5828,14 @@ ImgStringWrite(interp, formatString, blockPtr) * * Tk_PhotoGetImage -- * - * This procedure is called to obtain image data from a photo - * image. This procedure fills in the Tk_PhotoImageBlock structure - * pointed to by `blockPtr' with details of the address and - * layout of the image data in memory. + * This function is called to obtain image data from a photo image. This + * function fills in the Tk_PhotoImageBlock structure pointed to by + * `blockPtr' with details of the address and layout of the image data in + * memory. * * Results: - * TRUE (1) indicating that image data is available, - * for backwards compatibility with the old photo widget. + * TRUE (1) indicating that image data is available, for backwards + * compatibility with the old photo widget. * * Side effects: * None. @@ -5838,16 +5844,15 @@ ImgStringWrite(interp, formatString, blockPtr) */ int -Tk_PhotoGetImage(handle, blockPtr) - Tk_PhotoHandle handle; /* Handle for the photo image from which - * image data is desired. */ - Tk_PhotoImageBlock *blockPtr; - /* Information about the address and layout - * of the image data is returned here. */ +Tk_PhotoGetImage( + Tk_PhotoHandle handle, /* Handle for the photo image from which image + * data is desired. */ + Tk_PhotoImageBlock *blockPtr) + /* Information about the address and layout of + * the image data is returned here. */ { - PhotoMaster *masterPtr; + PhotoMaster *masterPtr = (PhotoMaster *) handle; - masterPtr = (PhotoMaster *) handle; blockPtr->pixelPtr = masterPtr->pix32; blockPtr->width = masterPtr->width; blockPtr->height = masterPtr->height; @@ -5859,7 +5864,7 @@ Tk_PhotoGetImage(handle, blockPtr) blockPtr->offset[3] = 3; return 1; } - + /* *---------------------------------------------------------------------- * @@ -5877,57 +5882,56 @@ Tk_PhotoGetImage(handle, blockPtr) */ typedef struct OptionAssocData { - struct OptionAssocData *nextPtr; /* pointer to next OptionAssocData */ - Tcl_ObjCmdProc *command; /* command associated with this - * option */ - char name[1]; /* name of option (remaining chars) */ + struct OptionAssocData *nextPtr; + /* Pointer to next OptionAssocData. */ + Tcl_ObjCmdProc *command; /* Command associated with this option. */ + char name[1]; /* Name of option (remaining chars) */ } OptionAssocData; static Tcl_ObjCmdProc * -PhotoOptionFind(interp, obj) - Tcl_Interp *interp; /* Interpreter that is being deleted. */ - Tcl_Obj *obj; /* Name of option to be found. */ +PhotoOptionFind( + Tcl_Interp *interp, /* Interpreter that is being deleted. */ + Tcl_Obj *obj) /* Name of option to be found. */ { int length; char *name = Tcl_GetStringFromObj(obj, &length); - OptionAssocData *list; char *prevname = NULL; - Tcl_ObjCmdProc *proc = (Tcl_ObjCmdProc *) NULL; + Tcl_ObjCmdProc *proc = NULL; + OptionAssocData *list = (OptionAssocData *) Tcl_GetAssocData(interp, + "photoOption", NULL); - list = (OptionAssocData *) Tcl_GetAssocData(interp, "photoOption", - (Tcl_InterpDeleteProc **) NULL); - while (list != (OptionAssocData *) NULL) { + while (list != NULL) { if (strncmp(name, list->name, (unsigned) length) == 0) { - if (proc != (Tcl_ObjCmdProc *) NULL) { + if (proc != NULL) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "ambiguous option \"", name, - "\": must be ", prevname, (char *) NULL); - while (list->nextPtr != (OptionAssocData *) NULL) { - Tcl_AppendResult(interp, prevname, ", ",(char *) NULL); + "\": must be ", prevname, NULL); + while (list->nextPtr != NULL) { + Tcl_AppendResult(interp, prevname, ", ",NULL); list = list->nextPtr; prevname = list->name; } - Tcl_AppendResult(interp, ", or", prevname, (char *) NULL); - return (Tcl_ObjCmdProc *) NULL; + Tcl_AppendResult(interp, ", or", prevname, NULL); + return NULL; } proc = list->command; prevname = list->name; } list = list->nextPtr; } - if (proc != (Tcl_ObjCmdProc *) NULL) { + if (proc != NULL) { Tcl_ResetResult(interp); } return proc; } - + /* *---------------------------------------------------------------------- * * PhotoOptionCleanupProc -- * - * This procedure is invoked whenever an interpreter is deleted - * to cleanup the AssocData for "photoVisitor". + * This function is invoked whenever an interpreter is deleted to cleanup + * the AssocData for "photoVisitor". * * Results: * None. @@ -5939,49 +5943,47 @@ PhotoOptionFind(interp, obj) */ static void -PhotoOptionCleanupProc(clientData, interp) - ClientData clientData; /* Points to "photoVisitor" AssocData - * for the interpreter. */ - Tcl_Interp *interp; /* Interpreter that is being deleted. */ +PhotoOptionCleanupProc( + ClientData clientData, /* Points to "photoVisitor" AssocData for the + * interpreter. */ + Tcl_Interp *interp) /* Interpreter that is being deleted. */ { OptionAssocData *list = (OptionAssocData *) clientData; - OptionAssocData *ptr; while (list != NULL) { + register OptionAssocData *ptr; + list = (ptr = list)->nextPtr; ckfree((char *) ptr); } } - + /* *-------------------------------------------------------------- * * Tk_CreatePhotoOption -- * - * This procedure may be invoked to add a new kind of photo - * option to the core photo command supported by Tk. + * This function may be invoked to add a new kind of photo option to the + * core photo command supported by Tk. * * Results: * None. * * Side effects: - * From now on, the new option will be useable by the - * photo command. + * From now on, the new option will be useable by the photo command. * *-------------------------------------------------------------- */ -void -Tk_CreatePhotoOption(interp, name, proc) - Tcl_Interp *interp; /* interpreter */ - CONST char *name; /* option name */ - Tcl_ObjCmdProc *proc; /* proc to execute command */ +MODULE_SCOPE void +Tk_CreatePhotoOption( + Tcl_Interp *interp, /* Interpreter. */ + CONST char *name, /* Option name. */ + Tcl_ObjCmdProc *proc) /* Function to execute command. */ { OptionAssocData *typePtr2, *prevPtr, *ptr; - OptionAssocData *list; - - list = (OptionAssocData *) Tcl_GetAssocData(interp, "photoOption", - (Tcl_InterpDeleteProc **) NULL); + OptionAssocData *list = (OptionAssocData *) + Tcl_GetAssocData(interp, "photoOption", NULL); /* * If there's already a photo option with the given name, remove it. @@ -6004,7 +6006,7 @@ Tk_CreatePhotoOption(interp, name, proc) ptr->command = proc; ptr->nextPtr = list; Tcl_SetAssocData(interp, "photoOption", PhotoOptionCleanupProc, - (ClientData) ptr); + (ClientData) ptr); } /* @@ -6012,9 +6014,8 @@ Tk_CreatePhotoOption(interp, name, proc) * * TkPostscriptPhoto -- * - * This procedure is called to output the contents of a - * photo image in Postscript by calling the Tk_PostscriptPhoto - * function. + * This function is called to output the contents of a photo image in + * Postscript by calling the Tk_PostscriptPhoto function. * * Results: * Returns a standard Tcl return value. @@ -6024,16 +6025,16 @@ Tk_CreatePhotoOption(interp, name, proc) * *-------------------------------------------------------------- */ + static int -ImgPhotoPostscript(clientData, interp, tkwin, psInfo, - x, y, width, height, prepass) - ClientData clientData; /* Handle for the photo image */ - Tcl_Interp *interp; /* Interpreter */ - Tk_Window tkwin; /* (unused) */ - Tk_PostscriptInfo psInfo; /* postscript info */ - int x, y; /* First pixel to output */ - int width, height; /* Width and height of area */ - int prepass; /* (unused) */ +ImgPhotoPostscript( + ClientData clientData, /* Handle for the photo image. */ + Tcl_Interp *interp, /* Interpreter. */ + Tk_Window tkwin, /* (unused) */ + Tk_PostscriptInfo psInfo, /* Postscript info. */ + int x, int y, /* First pixel to output. */ + int width, int height, /* Width and height of area. */ + int prepass) /* (unused) */ { Tk_PhotoImageBlock block; @@ -6048,29 +6049,105 @@ ImgPhotoPostscript(clientData, interp, tkwin, psInfo, * * Tk_PhotoPutBlock_NoComposite, Tk_PhotoPutZoomedBlock_NoComposite -- * - * These backward-compatability functions just exist to fill slots in - * stubs table. For the behaviour of *_NoComposite, refer to the - * corresponding function without the extra suffix. + * These backward-compatability functions just exist to fill slots in stubs + * table. For the behaviour of *_NoComposite, refer to the corresponding + * function without the extra suffix, except that the compositing rule is + * always "overlay" and the function always panics on memory-allocation + * failure. * *---------------------------------------------------------------------- */ + void -Tk_PhotoPutBlock_NoComposite(handle, blockPtr, x, y, width, height) - Tk_PhotoHandle handle; - Tk_PhotoImageBlock *blockPtr; - int x, y, width, height; +Tk_PhotoPutBlock_NoComposite( + Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr, + int x, int y, int width, int height) { - Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, - TK_PHOTO_COMPOSITE_OVERLAY); + if (Tk_PhotoPutBlock(NULL, handle, blockPtr, x, y, width, height, + TK_PHOTO_COMPOSITE_OVERLAY) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } } void -Tk_PhotoPutZoomedBlock_NoComposite(handle, blockPtr, x, y, width, height, - zoomX, zoomY, subsampleX, subsampleY) - Tk_PhotoHandle handle; - Tk_PhotoImageBlock *blockPtr; - int x, y, width, height, zoomX, zoomY, subsampleX, subsampleY; +Tk_PhotoPutZoomedBlock_NoComposite( + Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr, + int x, int y, int width, int height, + int zoomX, int zoomY, int subsampleX, int subsampleY) { - Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, - zoomX, zoomY, subsampleX, subsampleY, TK_PHOTO_COMPOSITE_OVERLAY); + if (Tk_PhotoPutZoomedBlock(NULL, handle, blockPtr, x, y, width, height, + zoomX, zoomY, subsampleX, subsampleY, + TK_PHOTO_COMPOSITE_OVERLAY) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } } + +/* + *---------------------------------------------------------------------- + * + * Tk_PhotoExpand_Panic, Tk_PhotoPutBlock_Panic, + * Tk_PhotoPutZoomedBlock_Panic, Tk_PhotoSetSize_Panic + * + * Backward compatability functions for preserving the old behaviour (i.e. + * panic on memory allocation failure) so that extensions do not need to be + * significantly updated to take account of TIP #116. These call the new + * interface (i.e. the interface without the extra suffix), but panic if an + * error condition is returned. + * + *---------------------------------------------------------------------- + */ + +void +Tk_PhotoExpand_Panic( + Tk_PhotoHandle handle, + int width, int height) +{ + if (Tk_PhotoExpand(NULL, handle, width, height) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } +} + +void +Tk_PhotoPutBlock_Panic( + Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr, + int x, int y, int width, int height, int compRule) +{ + if (Tk_PhotoPutBlock(NULL, handle, blockPtr, x, y, width, height, + compRule) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } +} + +void +Tk_PhotoPutZoomedBlock_Panic( + Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, + int x, int y, int width, int height, + int zoomX, int zoomY, int subsampleX, int subsampleY, + int compRule) +{ + if (Tk_PhotoPutZoomedBlock(NULL, handle, blockPtr, x, y, width, height, + zoomX, zoomY, subsampleX, subsampleY, compRule) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } +} + +void +Tk_PhotoSetSize_Panic( + Tk_PhotoHandle handle, + int width, int height) +{ + if (Tk_PhotoSetSize(NULL, handle, width, height) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |