tkImgPhoto.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:171k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkImgPhoto.c --
  3.  *
  4.  * Implements images of type "photo" for Tk.  Photo images are
  5.  * stored in full color (32 bits per pixel including alpha channel)
  6.  * and displayed using dithering if necessary.
  7.  *
  8.  * Copyright (c) 1994 The Australian National University.
  9.  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
  10.  * Copyright (c) 2002 Donal K. Fellows
  11.  * Copyright (c) 2003 ActiveState Corporation.
  12.  *
  13.  * See the file "license.terms" for information on usage and redistribution
  14.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  15.  *
  16.  * Author: Paul Mackerras (paulus@cs.anu.edu.au),
  17.  *    Department of Computer Science,
  18.  *    Australian National University.
  19.  *
  20.  * RCS: @(#) $Id: tkImgPhoto.c,v 1.36.2.18 2007/06/23 00:26:42 das Exp $
  21.  */
  22. #include "tkInt.h"
  23. #include "tkPort.h"
  24. #include "tclMath.h"
  25. #include <ctype.h>
  26. #ifdef __WIN32__
  27. #include "tkWinInt.h"
  28. #endif
  29. /*
  30.  * Declaration for internal Xlib function used here:
  31.  */
  32. extern int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image));
  33. /*
  34.  * A signed 8-bit integral type.  If chars are unsigned and the compiler
  35.  * isn't an ANSI one, then we have to use short instead (which wastes
  36.  * space) to get signed behavior.
  37.  */
  38. #if defined(__STDC__) || defined(_AIX)
  39.     typedef signed char schar;
  40. #else
  41. #   ifndef __CHAR_UNSIGNED__
  42. typedef char schar;
  43. #   else
  44. typedef short schar;
  45. #   endif
  46. #endif
  47. /*
  48.  * An unsigned 32-bit integral type, used for pixel values.
  49.  * We use int rather than long here to accommodate those systems
  50.  * where longs are 64 bits.
  51.  */
  52. typedef unsigned int pixel;
  53. /*
  54.  * The maximum number of pixels to transmit to the server in a
  55.  * single XPutImage call.
  56.  */
  57. #define MAX_PIXELS 65536
  58. /*
  59.  * The set of colors required to display a photo image in a window depends on:
  60.  * - the visual used by the window
  61.  * - the palette, which specifies how many levels of each primary
  62.  *   color to use, and
  63.  * - the gamma value for the image.
  64.  *
  65.  * Pixel values allocated for specific colors are valid only for the
  66.  * colormap in which they were allocated.  Sets of pixel values
  67.  * allocated for displaying photos are re-used in other windows if
  68.  * possible, that is, if the display, colormap, palette and gamma
  69.  * values match.  A hash table is used to locate these sets of pixel
  70.  * values, using the following data structure as key:
  71.  */
  72. typedef struct {
  73.     Display *display; /* Qualifies the colormap resource ID */
  74.     Colormap colormap; /* Colormap that the windows are using. */
  75.     double gamma; /* Gamma exponent value for images. */
  76.     Tk_Uid palette; /* Specifies how many shades of each primary
  77.  * we want to allocate. */
  78. } ColorTableId;
  79. /*
  80.  * For a particular (display, colormap, palette, gamma) combination,
  81.  * a data structure of the following type is used to store the allocated
  82.  * pixel values and other information:
  83.  */
  84. typedef struct ColorTable {
  85.     ColorTableId id; /* Information used in selecting this
  86.  * color table. */
  87.     int flags; /* See below. */
  88.     int refCount; /* Number of instances using this map. */
  89.     int liveRefCount; /* Number of instances which are actually
  90.  * in use, using this map. */
  91.     int numColors; /* Number of colors allocated for this map. */
  92.     XVisualInfo visualInfo; /* Information about the visual for windows
  93.  * using this color table. */
  94.     pixel redValues[256]; /* Maps 8-bit values of red intensity
  95.  * to a pixel value or index in pixelMap. */
  96.     pixel greenValues[256]; /* Ditto for green intensity */
  97.     pixel blueValues[256]; /* Ditto for blue intensity */
  98.     unsigned long *pixelMap; /* Actual pixel values allocated. */
  99.     unsigned char colorQuant[3][256];
  100. /* Maps 8-bit intensities to quantized
  101.  * intensities.  The first index is 0 for
  102.  * red, 1 for green, 2 for blue. */
  103. } ColorTable;
  104. /*
  105.  * Bit definitions for the flags field of a ColorTable.
  106.  * BLACK_AND_WHITE: 1 means only black and white colors are
  107.  * available.
  108.  * COLOR_WINDOW: 1 means a full 3-D color cube has been
  109.  * allocated.
  110.  * DISPOSE_PENDING: 1 means a call to DisposeColorTable has
  111.  * been scheduled as an idle handler, but it
  112.  * hasn't been invoked yet.
  113.  * MAP_COLORS: 1 means pixel values should be mapped
  114.  * through pixelMap.
  115.  */
  116. #ifdef COLOR_WINDOW
  117. #undef COLOR_WINDOW
  118. #endif
  119. #define BLACK_AND_WHITE 1
  120. #define COLOR_WINDOW 2
  121. #define DISPOSE_PENDING 4
  122. #define MAP_COLORS 8
  123. /*
  124.  * Definition of the data associated with each photo image master.
  125.  */
  126. typedef struct PhotoMaster {
  127.     Tk_ImageMaster tkMaster; /* Tk's token for image master.  NULL means
  128.  * the image is being deleted. */
  129.     Tcl_Interp *interp; /* Interpreter associated with the
  130.  * application using this image. */
  131.     Tcl_Command imageCmd; /* Token for image command (used to delete
  132.  * it when the image goes away).  NULL means
  133.  * the image command has already been
  134.  * deleted. */
  135.     int flags; /* Sundry flags, defined below. */
  136.     int width, height; /* Dimensions of image. */
  137.     int userWidth, userHeight; /* User-declared image dimensions. */
  138.     Tk_Uid palette; /* User-specified default palette for
  139.  * instances of this image. */
  140.     double gamma; /* Display gamma value to correct for. */
  141.     char *fileString; /* Name of file to read into image. */
  142.     Tcl_Obj *dataString; /* Object to use as contents of image. */
  143.     Tcl_Obj *format; /* User-specified format of data in image
  144.  * file or string value. */
  145.     unsigned char *pix32; /* Local storage for 32-bit image. */
  146.     int ditherX, ditherY; /* Location of first incorrectly
  147.  * dithered pixel in image. */
  148.     TkRegion validRegion; /* Tk region indicating which parts of
  149.  * the image have valid image data. */
  150.     struct PhotoInstance *instancePtr;
  151. /* First in the list of instances
  152.  * associated with this master. */
  153. } PhotoMaster;
  154. /*
  155.  * Bit definitions for the flags field of a PhotoMaster.
  156.  * COLOR_IMAGE: 1 means that the image has different color
  157.  * components.
  158.  * IMAGE_CHANGED: 1 means that the instances of this image
  159.  * need to be redithered.
  160.  * COMPLEX_ALPHA: 1 means that the instances of this image
  161.  * have alpha values that aren't 0 or 255.
  162.  */
  163. #define COLOR_IMAGE 1
  164. #define IMAGE_CHANGED 2
  165. #define COMPLEX_ALPHA 4
  166. /*
  167.  * Flag to OR with the compositing rule to indicate that the source, despite
  168.  * having an alpha channel, has simple alpha.
  169.  */
  170. #define SOURCE_IS_SIMPLE_ALPHA_PHOTO 0x10000000
  171. /*
  172.  * The following data structure represents all of the instances of
  173.  * a photo image in windows on a given screen that are using the
  174.  * same colormap.
  175.  */
  176. typedef struct PhotoInstance {
  177.     PhotoMaster *masterPtr; /* Pointer to master for image. */
  178.     Display *display; /* Display for windows using this instance. */
  179.     Colormap colormap; /* The image may only be used in windows with
  180.  * this particular colormap. */
  181.     struct PhotoInstance *nextPtr;
  182. /* Pointer to the next instance in the list
  183.  * of instances associated with this master. */
  184.     int refCount; /* Number of instances using this structure. */
  185.     Tk_Uid palette; /* Palette for these particular instances. */
  186.     double gamma; /* Gamma value for these instances. */
  187.     Tk_Uid defaultPalette; /* Default palette to use if a palette
  188.  * is not specified for the master. */
  189.     ColorTable *colorTablePtr; /* Pointer to information about colors
  190.  * allocated for image display in windows
  191.  * like this one. */
  192.     Pixmap pixels; /* X pixmap containing dithered image. */
  193.     int width, height; /* Dimensions of the pixmap. */
  194.     schar *error; /* Error image, used in dithering. */
  195.     XImage *imagePtr; /* Image structure for converted pixels. */
  196.     XVisualInfo visualInfo; /* Information about the visual that these
  197.  * windows are using. */
  198.     GC gc; /* Graphics context for writing images
  199.  * to the pixmap. */
  200. } PhotoInstance;
  201. /*
  202.  * The following data structure is used to return information
  203.  * from ParseSubcommandOptions:
  204.  */
  205. struct SubcommandOptions {
  206.     int options; /* Individual bits indicate which
  207.  * options were specified - see below. */
  208.     Tcl_Obj *name; /* Name specified without an option. */
  209.     int fromX, fromY; /* Values specified for -from option. */
  210.     int fromX2, fromY2; /* Second coordinate pair for -from option. */
  211.     int toX, toY; /* Values specified for -to option. */
  212.     int toX2, toY2; /* Second coordinate pair for -to option. */
  213.     int zoomX, zoomY; /* Values specified for -zoom option. */
  214.     int subsampleX, subsampleY; /* Values specified for -subsample option. */
  215.     Tcl_Obj *format; /* Value specified for -format option. */
  216.     XColor *background; /* Value specified for -background option. */
  217.     int compositingRule; /* Value specified for -compositingrule opt */
  218. };
  219. /*
  220.  * Bit definitions for use with ParseSubcommandOptions:
  221.  * Each bit is set in the allowedOptions parameter on a call to
  222.  * ParseSubcommandOptions if that option is allowed for the current
  223.  * photo image subcommand.  On return, the bit is set in the options
  224.  * field of the SubcommandOptions structure if that option was specified.
  225.  *
  226.  * OPT_BACKGROUND: Set if -format option allowed/specified.
  227.  * OPT_COMPOSITE: Set if -compositingrule option allowed/spec'd.
  228.  * OPT_FORMAT: Set if -format option allowed/specified.
  229.  * OPT_FROM: Set if -from option allowed/specified.
  230.  * OPT_GRAYSCALE: Set if -grayscale option allowed/specified.
  231.  * OPT_SHRINK: Set if -shrink option allowed/specified.
  232.  * OPT_SUBSAMPLE: Set if -subsample option allowed/spec'd.
  233.  * OPT_TO: Set if -to option allowed/specified.
  234.  * OPT_ZOOM: Set if -zoom option allowed/specified.
  235.  */
  236. #define OPT_BACKGROUND 1
  237. #define OPT_COMPOSITE 2
  238. #define OPT_FORMAT 4
  239. #define OPT_FROM 8
  240. #define OPT_GRAYSCALE 0x10
  241. #define OPT_SHRINK 0x20
  242. #define OPT_SUBSAMPLE 0x40
  243. #define OPT_TO 0x80
  244. #define OPT_ZOOM 0x100
  245. /*
  246.  * List of option names.  The order here must match the order of
  247.  * declarations of the OPT_* constants above.
  248.  */
  249. static char *optionNames[] = {
  250.     "-background",
  251.     "-compositingrule",
  252.     "-format",
  253.     "-from",
  254.     "-grayscale",
  255.     "-shrink",
  256.     "-subsample",
  257.     "-to",
  258.     "-zoom",
  259.     (char *) NULL
  260. };
  261. /*
  262.  * Message to generate when an attempt to resize an image fails due
  263.  * to memory problems.
  264.  */
  265. #define TK_PHOTO_ALLOC_FAILURE_MESSAGE 
  266. "not enough free memory for image buffer"
  267. /*
  268.  * Functions used in the type record for photo images.
  269.  */
  270. static int ImgPhotoCreate _ANSI_ARGS_((Tcl_Interp *interp,
  271.     char *name, int objc, Tcl_Obj *CONST objv[],
  272.     Tk_ImageType *typePtr, Tk_ImageMaster master,
  273.     ClientData *clientDataPtr));
  274. static ClientData ImgPhotoGet _ANSI_ARGS_((Tk_Window tkwin,
  275.     ClientData clientData));
  276. static void ImgPhotoDisplay _ANSI_ARGS_((ClientData clientData,
  277.     Display *display, Drawable drawable,
  278.     int imageX, int imageY, int width, int height,
  279.     int drawableX, int drawableY));
  280. static void ImgPhotoFree _ANSI_ARGS_((ClientData clientData,
  281.     Display *display));
  282. static void ImgPhotoDelete _ANSI_ARGS_((ClientData clientData));
  283. static int ImgPhotoPostscript _ANSI_ARGS_((ClientData clientData,
  284.     Tcl_Interp *interp, Tk_Window tkwin,
  285.     Tk_PostscriptInfo psInfo, int x, int y, int width,
  286.     int height, int prepass));
  287. /*
  288.  * The type record itself for photo images:
  289.  */
  290. Tk_ImageType tkPhotoImageType = {
  291.     "photo", /* name */
  292.     ImgPhotoCreate, /* createProc */
  293.     ImgPhotoGet, /* getProc */
  294.     ImgPhotoDisplay, /* displayProc */
  295.     ImgPhotoFree, /* freeProc */
  296.     ImgPhotoDelete, /* deleteProc */
  297.     ImgPhotoPostscript, /* postscriptProc */
  298.     (Tk_ImageType *) NULL /* nextPtr */
  299. };
  300. typedef struct ThreadSpecificData {
  301.     Tk_PhotoImageFormat *formatList;  /* Pointer to the first in the 
  302.        * list of known photo image formats.*/
  303.     Tk_PhotoImageFormat *oldFormatList;  /* Pointer to the first in the 
  304.        * list of known photo image formats.*/
  305.     int initialized; /* set to 1 if we've initialized the strucuture */
  306. } ThreadSpecificData;
  307. static Tcl_ThreadDataKey dataKey;
  308. /*
  309.  * Default configuration
  310.  */
  311. #define DEF_PHOTO_GAMMA "1"
  312. #define DEF_PHOTO_HEIGHT "0"
  313. #define DEF_PHOTO_PALETTE ""
  314. #define DEF_PHOTO_WIDTH "0"
  315. /*
  316.  * Information used for parsing configuration specifications:
  317.  */
  318. static Tk_ConfigSpec configSpecs[] = {
  319.     {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
  320.  (char *) NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK},
  321.     {TK_CONFIG_DOUBLE, "-gamma", (char *) NULL, (char *) NULL,
  322.  DEF_PHOTO_GAMMA, Tk_Offset(PhotoMaster, gamma), 0},
  323.     {TK_CONFIG_INT, "-height", (char *) NULL, (char *) NULL,
  324.  DEF_PHOTO_HEIGHT, Tk_Offset(PhotoMaster, userHeight), 0},
  325.     {TK_CONFIG_UID, "-palette", (char *) NULL, (char *) NULL,
  326.  DEF_PHOTO_PALETTE, Tk_Offset(PhotoMaster, palette), 0},
  327.     {TK_CONFIG_INT, "-width", (char *) NULL, (char *) NULL,
  328.  DEF_PHOTO_WIDTH, Tk_Offset(PhotoMaster, userWidth), 0},
  329.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  330.  (char *) NULL, 0, 0}
  331. };
  332. /*
  333.  * Hash table used to hash from (display, colormap, palette, gamma)
  334.  * to ColorTable address.
  335.  */
  336. static Tcl_HashTable imgPhotoColorHash;
  337. static int imgPhotoColorHashInitialized;
  338. #define N_COLOR_HASH (sizeof(ColorTableId) / sizeof(int))
  339. /*
  340.  * Implementation of the Porter-Duff Source-Over compositing rule.
  341.  */
  342. #define PD_SRC_OVER(srcColor,srcAlpha,dstColor,dstAlpha) 
  343. (srcColor*srcAlpha/255) + dstAlpha*(255-srcAlpha)/255*dstColor/255
  344. #define PD_SRC_OVER_ALPHA(srcAlpha,dstAlpha) 
  345. (srcAlpha + (255-srcAlpha)*dstAlpha/255)
  346. /*
  347.  * Forward declarations
  348.  */
  349. static void PhotoFormatThreadExitProc _ANSI_ARGS_((
  350.     ClientData clientData));
  351. static int ImgPhotoCmd _ANSI_ARGS_((ClientData clientData,
  352.     Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
  353. static int ParseSubcommandOptions _ANSI_ARGS_((
  354.     struct SubcommandOptions *optPtr,
  355.     Tcl_Interp *interp, int allowedOptions,
  356.     int *indexPtr, int objc, Tcl_Obj *CONST objv[]));
  357. static void ImgPhotoCmdDeletedProc _ANSI_ARGS_((
  358.     ClientData clientData));
  359. static int ImgPhotoConfigureMaster _ANSI_ARGS_((
  360.     Tcl_Interp *interp, PhotoMaster *masterPtr,
  361.     int objc, Tcl_Obj *CONST objv[], int flags));
  362. static void ImgPhotoConfigureInstance _ANSI_ARGS_((
  363.     PhotoInstance *instancePtr));
  364. static int              ToggleComplexAlphaIfNeeded _ANSI_ARGS_((
  365.                             PhotoMaster *mPtr));
  366. static void             ImgPhotoBlendComplexAlpha _ANSI_ARGS_((
  367.     XImage *bgImg, PhotoInstance *iPtr,
  368.     int xOffset, int yOffset, int width, int height));
  369. static int ImgPhotoSetSize _ANSI_ARGS_((PhotoMaster *masterPtr,
  370.     int width, int height));
  371. static void ImgPhotoInstanceSetSize _ANSI_ARGS_((
  372.     PhotoInstance *instancePtr));
  373. static int ImgStringWrite _ANSI_ARGS_((Tcl_Interp *interp,
  374.     Tcl_Obj *formatString,
  375.     Tk_PhotoImageBlock *blockPtr));
  376. static char * ImgGetPhoto _ANSI_ARGS_((PhotoMaster *masterPtr,
  377.     Tk_PhotoImageBlock *blockPtr,
  378.     struct SubcommandOptions *optPtr));
  379. static int IsValidPalette _ANSI_ARGS_((PhotoInstance *instancePtr,
  380.     CONST char *palette));
  381. static int CountBits _ANSI_ARGS_((pixel mask));
  382. static void GetColorTable _ANSI_ARGS_((PhotoInstance *instancePtr));
  383. static void FreeColorTable _ANSI_ARGS_((ColorTable *colorPtr,
  384.     int force));
  385. static void AllocateColors _ANSI_ARGS_((ColorTable *colorPtr));
  386. static void DisposeColorTable _ANSI_ARGS_((ClientData clientData));
  387. static void DisposeInstance _ANSI_ARGS_((ClientData clientData));
  388. static int ReclaimColors _ANSI_ARGS_((ColorTableId *id,
  389.     int numColors));
  390. static int MatchFileFormat _ANSI_ARGS_((Tcl_Interp *interp,
  391.     Tcl_Channel chan, char *fileName, Tcl_Obj *formatString,
  392.     Tk_PhotoImageFormat **imageFormatPtr,
  393.     int *widthPtr, int *heightPtr, int *oldformat));
  394. static int MatchStringFormat _ANSI_ARGS_((Tcl_Interp *interp,
  395.     Tcl_Obj *data, Tcl_Obj *formatString,
  396.     Tk_PhotoImageFormat **imageFormatPtr,
  397.     int *widthPtr, int *heightPtr, int *oldformat));
  398. static Tcl_ObjCmdProc * PhotoOptionFind _ANSI_ARGS_((Tcl_Interp * interp,
  399.     Tcl_Obj *obj));
  400. static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr,
  401.     int x, int y, int width, int height));
  402. static void PhotoOptionCleanupProc _ANSI_ARGS_((
  403.     ClientData clientData, Tcl_Interp *interp));
  404. #undef MIN
  405. #define MIN(a, b) ((a) < (b)? (a): (b))
  406. #undef MAX
  407. #define MAX(a, b) ((a) > (b)? (a): (b))
  408. /*
  409.  *----------------------------------------------------------------------
  410.  *
  411.  * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat --
  412.  *
  413.  * This procedure is invoked by an image file handler to register
  414.  * a new photo image format and the procedures that handle the
  415.  * new format.  The procedure is typically invoked during
  416.  * Tcl_AppInit.
  417.  *
  418.  * Results:
  419.  * None.
  420.  *
  421.  * Side effects:
  422.  * The new image file format is entered into a table used in the
  423.  * photo image "read" and "write" subcommands.
  424.  *
  425.  *----------------------------------------------------------------------
  426.  */
  427. static void
  428. PhotoFormatThreadExitProc(clientData)
  429.     ClientData clientData; /* not used */
  430. {
  431.     Tk_PhotoImageFormat *freePtr;
  432.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  433.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  434.     while (tsdPtr->oldFormatList != NULL) {
  435. freePtr = tsdPtr->oldFormatList;
  436. tsdPtr->oldFormatList = tsdPtr->oldFormatList->nextPtr;
  437. ckfree((char *) freePtr->name);
  438. ckfree((char *) freePtr);
  439.     }
  440.     while (tsdPtr->formatList != NULL) {
  441. freePtr = tsdPtr->formatList;
  442. tsdPtr->formatList = tsdPtr->formatList->nextPtr;
  443. ckfree((char *) freePtr->name);
  444. ckfree((char *) freePtr);
  445.     }
  446. }
  447. /*
  448.  *----------------------------------------------------------------------
  449.  *
  450.  * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat --
  451.  *
  452.  * This procedure is invoked by an image file handler to register
  453.  * a new photo image format and the procedures that handle the
  454.  * new format.  The procedure is typically invoked during
  455.  * Tcl_AppInit.
  456.  *
  457.  * Results:
  458.  * None.
  459.  *
  460.  * Side effects:
  461.  * The new image file format is entered into a table used in the
  462.  * photo image "read" and "write" subcommands.
  463.  *
  464.  *----------------------------------------------------------------------
  465.  */
  466. void
  467. Tk_CreateOldPhotoImageFormat(formatPtr)
  468.     Tk_PhotoImageFormat *formatPtr;
  469. /* Structure describing the format.  All of
  470.  * the fields except "nextPtr" must be filled
  471.  * in by caller.  Must not have been passed
  472.  * to Tk_CreatePhotoImageFormat previously. */
  473. {
  474.     Tk_PhotoImageFormat *copyPtr;
  475.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  476.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  477.     if (!tsdPtr->initialized) {
  478. tsdPtr->initialized = 1;
  479. Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);
  480.     }
  481.     copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat));
  482.     *copyPtr = *formatPtr;
  483.     copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1));
  484.     strcpy(copyPtr->name, formatPtr->name);
  485.     copyPtr->nextPtr = tsdPtr->oldFormatList;
  486.     tsdPtr->oldFormatList = copyPtr;
  487. }
  488. void
  489. Tk_CreatePhotoImageFormat(formatPtr)
  490.     Tk_PhotoImageFormat *formatPtr;
  491. /* Structure describing the format.  All of
  492.  * the fields except "nextPtr" must be filled
  493.  * in by caller.  Must not have been passed
  494.  * to Tk_CreatePhotoImageFormat previously. */
  495. {
  496.     Tk_PhotoImageFormat *copyPtr;
  497.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  498.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  499.     if (!tsdPtr->initialized) {
  500. tsdPtr->initialized = 1;
  501. Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);
  502.     }
  503.     copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat));
  504.     *copyPtr = *formatPtr;
  505.     copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1));
  506.     strcpy(copyPtr->name, formatPtr->name);
  507.     if (isupper((unsigned char) *formatPtr->name)) {
  508. copyPtr->nextPtr = tsdPtr->oldFormatList;
  509. tsdPtr->oldFormatList = copyPtr;
  510.     } else {
  511. copyPtr->nextPtr = tsdPtr->formatList;
  512. tsdPtr->formatList = copyPtr;
  513.     }
  514. }
  515. /*
  516.  *----------------------------------------------------------------------
  517.  *
  518.  * ImgPhotoCreate --
  519.  *
  520.  * This procedure is called by the Tk image code to create
  521.  * a new photo image.
  522.  *
  523.  * Results:
  524.  * A standard Tcl result.
  525.  *
  526.  * Side effects:
  527.  * The data structure for a new photo image is allocated and
  528.  * initialized.
  529.  *
  530.  *----------------------------------------------------------------------
  531.  */
  532. static int
  533. ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr)
  534.     Tcl_Interp *interp; /* Interpreter for application containing
  535.  * image. */
  536.     char *name; /* Name to use for image. */
  537.     int objc; /* Number of arguments. */
  538.     Tcl_Obj *CONST objv[]; /* Argument objects for options (doesn't
  539.  * include image name or type). */
  540.     Tk_ImageType *typePtr; /* Pointer to our type record (not used). */
  541.     Tk_ImageMaster master; /* Token for image, to be used by us in
  542.  * later callbacks. */
  543.     ClientData *clientDataPtr; /* Store manager's token for image here;
  544.  * it will be returned in later callbacks. */
  545. {
  546.     PhotoMaster *masterPtr;
  547.     /*
  548.      * Allocate and initialize the photo image master record.
  549.      */
  550.     masterPtr = (PhotoMaster *) ckalloc(sizeof(PhotoMaster));
  551.     memset((void *) masterPtr, 0, sizeof(PhotoMaster));
  552.     masterPtr->tkMaster = master;
  553.     masterPtr->interp = interp;
  554.     masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd,
  555.     (ClientData) masterPtr, ImgPhotoCmdDeletedProc);
  556.     masterPtr->palette = NULL;
  557.     masterPtr->pix32 = NULL;
  558.     masterPtr->instancePtr = NULL;
  559.     masterPtr->validRegion = TkCreateRegion();
  560.     /*
  561.      * Process configuration options given in the image create command.
  562.      */
  563.     if (ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, 0) != TCL_OK) {
  564. ImgPhotoDelete((ClientData) masterPtr);
  565. return TCL_ERROR;
  566.     }
  567.     *clientDataPtr = (ClientData) masterPtr;
  568.     return TCL_OK;
  569. }
  570. /*
  571.  *----------------------------------------------------------------------
  572.  *
  573.  * ImgPhotoCmd --
  574.  *
  575.  * This procedure is invoked to process the Tcl command that
  576.  * corresponds to a photo image.  See the user documentation
  577.  * for details on what it does.
  578.  *
  579.  * Results:
  580.  * A standard Tcl result.
  581.  *
  582.  * Side effects:
  583.  * See the user documentation.
  584.  *
  585.  *----------------------------------------------------------------------
  586.  */
  587. static int
  588. ImgPhotoCmd(clientData, interp, objc, objv)
  589.     ClientData clientData; /* Information about photo master. */
  590.     Tcl_Interp *interp; /* Current interpreter. */
  591.     int objc; /* Number of arguments. */
  592.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  593. {
  594.     int oldformat = 0;
  595.     static CONST char *photoOptions[] = {
  596. "blank", "cget", "configure", "copy", "data", "get", "put",
  597. "read", "redither", "transparency", "write", (char *) NULL
  598.     };
  599.     enum options {
  600. PHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA,
  601. PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_TRANS,
  602. PHOTO_WRITE
  603.     };
  604.     PhotoMaster *masterPtr = (PhotoMaster *) clientData;
  605.     int result, index;
  606.     int x, y, width, height;
  607.     int dataWidth, dataHeight;
  608.     struct SubcommandOptions options;
  609.     int listArgc;
  610.     CONST char **listArgv;
  611.     CONST char **srcArgv;
  612.     unsigned char *pixelPtr;
  613.     Tk_PhotoImageBlock block;
  614.     Tk_Window tkwin;
  615.     XColor color;
  616.     Tk_PhotoImageFormat *imageFormat;
  617.     int imageWidth, imageHeight;
  618.     int length, matched;
  619.     Tcl_Channel chan;
  620.     Tk_PhotoHandle srcHandle;
  621.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  622.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  623.     if (objc < 2) {
  624. Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
  625. return TCL_ERROR;
  626.     }
  627.     if (Tcl_GetIndexFromObj(interp, objv[1], photoOptions, "option", 0,
  628.     &index) != TCL_OK) {
  629. Tcl_ObjCmdProc *proc;
  630. proc = PhotoOptionFind(interp, objv[1]);
  631. if (proc == (Tcl_ObjCmdProc *) NULL) {
  632.     return TCL_ERROR;
  633. }
  634. return proc(clientData, interp, objc, objv);
  635.     }
  636.     switch ((enum options) index) {
  637.     case PHOTO_BLANK:
  638. /*
  639.  * photo blank command - just call Tk_PhotoBlank.
  640.  */
  641. if (objc == 2) {
  642.     Tk_PhotoBlank(masterPtr);
  643.     return TCL_OK;
  644. } else {
  645.     Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
  646.     return TCL_ERROR;
  647. }
  648.     case PHOTO_CGET: {
  649. char *arg;
  650. if (objc != 3) {
  651.     Tcl_WrongNumArgs(interp, 2, objv, "option");
  652.     return TCL_ERROR;
  653. }
  654. arg = Tcl_GetStringFromObj(objv[2], &length);
  655. if (strncmp(arg,"-data", (unsigned) length) == 0) {
  656.     if (masterPtr->dataString) {
  657. Tcl_SetObjResult(interp, masterPtr->dataString);
  658.     }
  659. } else if (strncmp(arg,"-format", (unsigned) length) == 0) {
  660.     if (masterPtr->format) {
  661. Tcl_SetObjResult(interp, masterPtr->format);
  662.     }
  663. } else {
  664.     Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
  665.     (char *) masterPtr, Tcl_GetString(objv[2]), 0);
  666. }
  667. return TCL_OK;
  668.     }
  669.     case PHOTO_CONFIGURE:
  670. /*
  671.  * photo configure command - handle this in the standard way.
  672.  */
  673. if (objc == 2) {
  674.     Tcl_Obj *obj, *subobj;
  675.     result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
  676.     configSpecs, (char *) masterPtr, (char *) NULL, 0);
  677.     if (result != TCL_OK) {
  678. return result;
  679.     }
  680.     obj = Tcl_NewObj();
  681.     subobj = Tcl_NewStringObj("-data {} {} {}", 14);
  682.     if (masterPtr->dataString) {
  683. Tcl_ListObjAppendElement(interp, subobj, masterPtr->dataString);
  684.     } else {
  685. Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL);
  686.     }
  687.     Tcl_ListObjAppendElement(interp, obj, subobj);
  688.     subobj = Tcl_NewStringObj("-format {} {} {}", 16);
  689.     if (masterPtr->format) {
  690. Tcl_ListObjAppendElement(interp, subobj, masterPtr->format);
  691.     } else {
  692. Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL);
  693.     }
  694.     Tcl_ListObjAppendElement(interp, obj, subobj);
  695.     Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp));
  696.     Tcl_SetObjResult(interp, obj);
  697.     return TCL_OK;
  698. }
  699. if (objc == 3) {
  700.     char *arg = Tcl_GetStringFromObj(objv[2], &length);
  701.     if (!strncmp(arg, "-data", (unsigned) length)) {
  702. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  703. "-data {} {} {}", (char *) NULL);
  704. if (masterPtr->dataString) {
  705.     Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
  706.     masterPtr->dataString);
  707. } else {
  708.     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  709.     " {}", (char *) NULL);
  710. }
  711. return TCL_OK;
  712.     } else if (!strncmp(arg, "-format", (unsigned) length)) {
  713. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  714. "-format {} {} {}", (char *) NULL);
  715. if (masterPtr->format) {
  716.     Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
  717.     masterPtr->format);
  718. } else {
  719.     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  720.     " {}", (char *) NULL);
  721. }
  722. return TCL_OK;
  723.     } else {
  724. return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
  725. configSpecs, (char *) masterPtr, arg, 0);
  726.     }
  727. }
  728. return ImgPhotoConfigureMaster(interp, masterPtr, objc-2, objv+2,
  729. TK_CONFIG_ARGV_ONLY);
  730.     case PHOTO_COPY:
  731. /*
  732.  * photo copy command - first parse options.
  733.  */
  734. index = 2;
  735. memset((VOID *) &options, 0, sizeof(options));
  736. options.zoomX = options.zoomY = 1;
  737. options.subsampleX = options.subsampleY = 1;
  738. options.name = NULL;
  739. options.compositingRule = TK_PHOTO_COMPOSITE_OVERLAY;
  740. if (ParseSubcommandOptions(&options, interp,
  741. OPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK |
  742. OPT_COMPOSITE, &index, objc, objv) != TCL_OK) {
  743.     return TCL_ERROR;
  744. }
  745. if (options.name == NULL || index < objc) {
  746.     Tcl_WrongNumArgs(interp, 2, objv,
  747.     "source-image ?-compositingrule rule? ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?");
  748.     return TCL_ERROR;
  749. }
  750. /*
  751.  * Look for the source image and get a pointer to its image data.
  752.  * Check the values given for the -from option.
  753.  */
  754. srcHandle = Tk_FindPhoto(interp, Tcl_GetString(options.name));
  755. if (srcHandle == NULL) {
  756.     Tcl_AppendResult(interp, "image "",
  757.     Tcl_GetString(options.name), "" doesn't",
  758.     " exist or is not a photo image", (char *) NULL);
  759.     return TCL_ERROR;
  760. }
  761. Tk_PhotoGetImage(srcHandle, &block);
  762. if ((options.fromX2 > block.width) || (options.fromY2 > block.height)
  763. || (options.fromX2 > block.width)
  764. || (options.fromY2 > block.height)) {
  765.     Tcl_AppendResult(interp, "coordinates for -from option extend ",
  766.     "outside source image", (char *) NULL);
  767.     return TCL_ERROR;
  768. }
  769. /*
  770.  * Hack to pass through the message that the place we're coming from
  771.  * has a simple alpha channel.
  772.  */
  773. if (!(((PhotoMaster *) srcHandle)->flags & COMPLEX_ALPHA)) {
  774.     options.compositingRule |= SOURCE_IS_SIMPLE_ALPHA_PHOTO;
  775. }
  776. /*
  777.  * Fill in default values for unspecified parameters.
  778.  */
  779. if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
  780.     options.fromX2 = block.width;
  781.     options.fromY2 = block.height;
  782. }
  783. if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
  784.     width = options.fromX2 - options.fromX;
  785.     if (options.subsampleX > 0) {
  786. width = (width + options.subsampleX - 1) / options.subsampleX;
  787.     } else if (options.subsampleX == 0) {
  788. width = 0;
  789.     } else {
  790. width = (width - options.subsampleX - 1) / -options.subsampleX;
  791.     }
  792.     options.toX2 = options.toX + width * options.zoomX;
  793.     height = options.fromY2 - options.fromY;
  794.     if (options.subsampleY > 0) {
  795. height = (height + options.subsampleY - 1)
  796. / options.subsampleY;
  797.     } else if (options.subsampleY == 0) {
  798. height = 0;
  799.     } else {
  800. height = (height - options.subsampleY - 1)
  801. / -options.subsampleY;
  802.     }
  803.     options.toY2 = options.toY + height * options.zoomY;
  804. }
  805. /*
  806.  * Set the destination image size if the -shrink option was specified.
  807.  */
  808. if (options.options & OPT_SHRINK) {
  809.     if (ImgPhotoSetSize(masterPtr, options.toX2,
  810.     options.toY2) != TCL_OK) {
  811. Tcl_ResetResult(interp);
  812. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  813. TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
  814. return TCL_ERROR;
  815.     }
  816. }
  817. /*
  818.  * Copy the image data over using Tk_PhotoPutZoomedBlock.
  819.  */
  820. block.pixelPtr += options.fromX * block.pixelSize
  821. + options.fromY * block.pitch;
  822. block.width = options.fromX2 - options.fromX;
  823. block.height = options.fromY2 - options.fromY;
  824. Tk_PhotoPutZoomedBlock((Tk_PhotoHandle) masterPtr, &block,
  825. options.toX, options.toY, options.toX2 - options.toX,
  826. options.toY2 - options.toY, options.zoomX, options.zoomY,
  827. options.subsampleX, options.subsampleY,
  828. options.compositingRule);
  829. return TCL_OK;
  830.     case PHOTO_DATA: {
  831. char *data;
  832. /*
  833.  * photo data command - first parse and check any options given.
  834.  */
  835. Tk_ImageStringWriteProc *stringWriteProc = NULL;
  836. index = 2;
  837. memset((VOID *) &options, 0, sizeof(options));
  838. options.name = NULL;
  839. options.format = NULL;
  840. options.fromX = 0;
  841. options.fromY = 0;
  842. if (ParseSubcommandOptions(&options, interp,
  843. OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
  844. &index, objc, objv) != TCL_OK) {
  845.     return TCL_ERROR;
  846. }
  847. if ((options.name != NULL) || (index < objc)) {
  848.     Tcl_WrongNumArgs(interp, 2, objv, "?options?");
  849.     return TCL_ERROR;
  850. }
  851. if ((options.fromX > masterPtr->width)
  852. || (options.fromY > masterPtr->height)
  853. || (options.fromX2 > masterPtr->width)
  854. || (options.fromY2 > masterPtr->height)) {
  855.     Tcl_AppendResult(interp, "coordinates for -from option extend ",
  856.     "outside image", (char *) NULL);
  857.     return TCL_ERROR;
  858. }
  859. /*
  860.  * Fill in default values for unspecified parameters.
  861.  */
  862. if (((options.options & OPT_FROM) == 0) || (options.fromX2 < 0)) {
  863.     options.fromX2 = masterPtr->width;
  864.     options.fromY2 = masterPtr->height;
  865. }
  866. /*
  867.  * Search for an appropriate image string format handler.
  868.  */
  869. if (options.options & OPT_FORMAT) {
  870.     matched = 0;
  871.     for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
  872.   imageFormat = imageFormat->nextPtr) {
  873. if ((strncasecmp(Tcl_GetString(options.format),
  874. imageFormat->name, strlen(imageFormat->name)) == 0)) {
  875.     matched = 1;
  876.     if (imageFormat->stringWriteProc != NULL) {
  877. stringWriteProc = imageFormat->stringWriteProc;
  878. break;
  879.     }
  880. }
  881.     }
  882.     if (stringWriteProc == NULL) {
  883. oldformat = 1;
  884. for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
  885. imageFormat = imageFormat->nextPtr) {
  886.     if ((strncasecmp(Tcl_GetString(options.format),
  887.     imageFormat->name,
  888.     strlen(imageFormat->name)) == 0)) {
  889. matched = 1;
  890. if (imageFormat->stringWriteProc != NULL) {
  891.     stringWriteProc = imageFormat->stringWriteProc;
  892.     break;
  893. }
  894.     }
  895. }
  896.     }
  897.     if (stringWriteProc == NULL) {
  898. Tcl_AppendResult(interp, "image string format "",
  899. Tcl_GetString(options.format), "" is ",
  900. (matched ? "not supported" : "unknown"),
  901. (char *) NULL);
  902. return TCL_ERROR;
  903.     }
  904. } else {
  905.     stringWriteProc = ImgStringWrite;
  906. }
  907. /*
  908.  * Call the handler's string write procedure to write out
  909.  * the image.
  910.  */
  911. data = ImgGetPhoto(masterPtr, &block, &options);
  912. if (oldformat) {
  913.     Tcl_DString buffer;
  914.     Tcl_DStringInit(&buffer);
  915.     result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp,
  916.     Tcl_DString *buffer, char *formatString,
  917.     Tk_PhotoImageBlock *blockPtr))) stringWriteProc)
  918.     (interp, &buffer, Tcl_GetString(options.format), &block);
  919.     if (result == TCL_OK) {
  920. Tcl_DStringResult(interp, &buffer);
  921.     } else {
  922. Tcl_DStringFree(&buffer);
  923.     }
  924. } else {
  925.     result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp,
  926.     Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr,
  927.     VOID *dummy))) stringWriteProc)
  928.     (interp, options.format, &block, (VOID *) NULL);
  929. }
  930. if (options.background) {
  931.     Tk_FreeColor(options.background);
  932. }
  933. if (data) {
  934.     ckfree(data);
  935. }
  936. return result;
  937.     }
  938.     case PHOTO_GET: {
  939. /*
  940.  * photo get command - first parse and check parameters.
  941.  */
  942. char string[TCL_INTEGER_SPACE * 3];
  943. if (objc != 4) {
  944.     Tcl_WrongNumArgs(interp, 2, objv, "x y");
  945.     return TCL_ERROR;
  946. }
  947. if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
  948. || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
  949.     return TCL_ERROR;
  950. }
  951. if ((x < 0) || (x >= masterPtr->width)
  952. || (y < 0) || (y >= masterPtr->height)) {
  953.     Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " get: ",
  954.     "coordinates out of range", (char *) NULL);
  955.     return TCL_ERROR;
  956. }
  957. /*
  958.  * Extract the value of the desired pixel and format it as a string.
  959.  */
  960. pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
  961. sprintf(string, "%d %d %d", pixelPtr[0], pixelPtr[1],
  962. pixelPtr[2]);
  963. Tcl_AppendResult(interp, string, (char *) NULL);
  964. return TCL_OK;
  965.     }
  966.     case PHOTO_PUT:
  967. /*
  968.  * photo put command - first parse the options and colors specified.
  969.  */
  970. index = 2;
  971. memset((VOID *) &options, 0, sizeof(options));
  972. options.name = NULL;
  973. if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT,
  974. &index, objc, objv) != TCL_OK) {
  975.     return TCL_ERROR;
  976. }
  977. if ((options.name == NULL) || (index < objc)) {
  978.     Tcl_WrongNumArgs(interp, 2, objv, "data ?options?");
  979.     return TCL_ERROR;
  980. }
  981. if (MatchStringFormat(interp, options.name ? objv[2]:NULL, 
  982. options.format, &imageFormat, &imageWidth,
  983. &imageHeight, &oldformat) == TCL_OK) {
  984.     Tcl_Obj *format, *data;
  985.     if (((options.options & OPT_TO) == 0) || (options.toX2 < 0)) {
  986. options.toX2 = options.toX + imageWidth;
  987. options.toY2 = options.toY + imageHeight;
  988.     }
  989.     if (imageWidth > options.toX2 - options.toX) {
  990. imageWidth = options.toX2 - options.toX;
  991.     }
  992.     if (imageHeight > options.toY2 - options.toY) {
  993. imageHeight = options.toY2 - options.toY;
  994.     }
  995.     format = options.format;
  996.     data = objv[2];
  997.     if (oldformat) {
  998. if (format) {
  999.     format = (Tcl_Obj *) Tcl_GetString(format);
  1000. }
  1001. data = (Tcl_Obj *) Tcl_GetString(data);
  1002.     }
  1003.     if ((*imageFormat->stringReadProc)(interp, data,
  1004.     format, (Tk_PhotoHandle) masterPtr,
  1005.     options.toX, options.toY, imageWidth, imageHeight,
  1006.     0, 0) != TCL_OK) {
  1007. return TCL_ERROR;
  1008.     }
  1009.     masterPtr->flags |= IMAGE_CHANGED;
  1010.     return TCL_OK;
  1011. }
  1012. if (options.options & OPT_FORMAT) {
  1013.     return TCL_ERROR;
  1014. }
  1015. Tcl_ResetResult(interp);
  1016. if (Tcl_SplitList(interp, Tcl_GetString(options.name),
  1017. &dataHeight, &srcArgv) != TCL_OK) {
  1018.     return TCL_ERROR;
  1019. }
  1020. tkwin = Tk_MainWindow(interp);
  1021. block.pixelPtr = NULL;
  1022. dataWidth = 0;
  1023. pixelPtr = NULL;
  1024. for (y = 0; y < dataHeight; ++y) {
  1025.     if (Tcl_SplitList(interp, srcArgv[y], &listArgc, &listArgv)
  1026.     != TCL_OK) {
  1027. break;
  1028.     }
  1029.     if (y == 0) {
  1030. if (listArgc == 0) {
  1031.     /*
  1032.      * Lines must be non-empty...
  1033.      */
  1034.     break;
  1035. }
  1036. dataWidth = listArgc;
  1037. pixelPtr = (unsigned char *)
  1038. ckalloc((unsigned) dataWidth * dataHeight * 3);
  1039. block.pixelPtr = pixelPtr;
  1040.     } else if (listArgc != dataWidth) {
  1041. Tcl_AppendResult(interp, "all elements of color list must",
  1042. " have the same number of elements", (char *) NULL);
  1043. ckfree((char *) listArgv);
  1044. break;
  1045.     }
  1046.     for (x = 0; x < dataWidth; ++x) {
  1047. if (!XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
  1048. listArgv[x], &color)) {
  1049.     Tcl_AppendResult(interp, "can't parse color "",
  1050.     listArgv[x], """, (char *) NULL);
  1051.     break;
  1052. }
  1053. *pixelPtr++ = color.red >> 8;
  1054. *pixelPtr++ = color.green >> 8;
  1055. *pixelPtr++ = color.blue >> 8;
  1056.     }
  1057.     ckfree((char *) listArgv);
  1058.     if (x < dataWidth) {
  1059. break;
  1060.     }
  1061. }
  1062. ckfree((char *) srcArgv);
  1063. if (y < dataHeight || dataHeight == 0 || dataWidth == 0) {
  1064.     if (block.pixelPtr != NULL) {
  1065. ckfree((char *) block.pixelPtr);
  1066.     }
  1067.     if (y < dataHeight) {
  1068. return TCL_ERROR;
  1069.     }
  1070.     return TCL_OK;
  1071. }
  1072. /*
  1073.  * Fill in default values for the -to option, then
  1074.  * copy the block in using Tk_PhotoPutBlock.
  1075.  */
  1076. if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
  1077.     options.toX2 = options.toX + dataWidth;
  1078.     options.toY2 = options.toY + dataHeight;
  1079. }
  1080. block.width = dataWidth;
  1081. block.height = dataHeight;
  1082. block.pitch = dataWidth * 3;
  1083. block.pixelSize = 3;
  1084. block.offset[0] = 0;
  1085. block.offset[1] = 1;
  1086. block.offset[2] = 2;
  1087. block.offset[3] = 0;
  1088. Tk_PhotoPutBlock((ClientData)masterPtr, &block,
  1089. options.toX, options.toY, options.toX2 - options.toX,
  1090. options.toY2 - options.toY, TK_PHOTO_COMPOSITE_SET);
  1091. ckfree((char *) block.pixelPtr);
  1092. return TCL_OK;
  1093.     case PHOTO_READ: {
  1094. Tcl_Obj *format;
  1095. /*
  1096.  * photo read command - first parse the options specified.
  1097.  */
  1098. index = 2;
  1099. memset((VOID *) &options, 0, sizeof(options));
  1100. options.name = NULL;
  1101. options.format = NULL;
  1102. if (ParseSubcommandOptions(&options, interp,
  1103. OPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK,
  1104. &index, objc, objv) != TCL_OK) {
  1105.     return TCL_ERROR;
  1106. }
  1107. if ((options.name == NULL) || (index < objc)) {
  1108.     Tcl_WrongNumArgs(interp, 2, objv, "fileName ?options?");
  1109.     return TCL_ERROR;
  1110. }
  1111.         /*
  1112.          * Prevent file system access in safe interpreters.
  1113.          */
  1114.         if (Tcl_IsSafe(interp)) {
  1115.             Tcl_AppendResult(interp, "can't get image from a file in a",
  1116.     " safe interpreter", (char *) NULL);
  1117.             return TCL_ERROR;
  1118.         }
  1119.         
  1120. /*
  1121.  * Open the image file and look for a handler for it.
  1122.  */
  1123. chan = Tcl_OpenFileChannel(interp,
  1124. Tcl_GetString(options.name), "r", 0);
  1125. if (chan == NULL) {
  1126.     return TCL_ERROR;
  1127. }
  1128.         if (Tcl_SetChannelOption(interp, chan, "-translation", "binary")
  1129. != TCL_OK) {
  1130.     Tcl_Close(NULL, chan);
  1131.             return TCL_ERROR;
  1132.         }
  1133.         if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary")
  1134. != TCL_OK) {
  1135.     Tcl_Close(NULL, chan);
  1136.             return TCL_ERROR;
  1137.         }
  1138.     
  1139. if (MatchFileFormat(interp, chan,
  1140. Tcl_GetString(options.name), options.format, &imageFormat,
  1141. &imageWidth, &imageHeight, &oldformat) != TCL_OK) {
  1142.     Tcl_Close(NULL, chan);
  1143.     return TCL_ERROR;
  1144. }
  1145. /*
  1146.  * Check the values given for the -from option.
  1147.  */
  1148. if ((options.fromX > imageWidth) || (options.fromY > imageHeight)
  1149. || (options.fromX2 > imageWidth)
  1150. || (options.fromY2 > imageHeight)) {
  1151.     Tcl_AppendResult(interp, "coordinates for -from option extend ",
  1152.     "outside source image", (char *) NULL);
  1153.     Tcl_Close(NULL, chan);
  1154.     return TCL_ERROR;
  1155. }
  1156. if (((options.options & OPT_FROM) == 0) || (options.fromX2 < 0)) {
  1157.     width = imageWidth - options.fromX;
  1158.     height = imageHeight - options.fromY;
  1159. } else {
  1160.     width = options.fromX2 - options.fromX;
  1161.     height = options.fromY2 - options.fromY;
  1162. }
  1163. /*
  1164.  * If the -shrink option was specified, set the size of the image.
  1165.  */
  1166. if (options.options & OPT_SHRINK) {
  1167.     if (ImgPhotoSetSize(masterPtr, options.toX + width,
  1168.     options.toY + height) != TCL_OK) {
  1169. Tcl_ResetResult(interp);
  1170. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1171. TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
  1172. return TCL_ERROR;
  1173.     }
  1174. }
  1175. /*
  1176.  * Call the handler's file read procedure to read the data
  1177.  * into the image.
  1178.  */
  1179. format = options.format;
  1180. if (oldformat && format) {
  1181.     format = (Tcl_Obj *) Tcl_GetString(format);
  1182. }
  1183. result = (*imageFormat->fileReadProc)(interp, chan,
  1184. Tcl_GetString(options.name),
  1185. format, (Tk_PhotoHandle) masterPtr, options.toX,
  1186. options.toY, width, height, options.fromX, options.fromY);
  1187. if (chan != NULL) {
  1188.     Tcl_Close(NULL, chan);
  1189. }
  1190. return result;
  1191.     }
  1192.     case PHOTO_REDITHER:
  1193. if (objc != 2) {
  1194.     Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
  1195.     return TCL_ERROR;
  1196. }
  1197. /*
  1198.  * Call Dither if any part of the image is not correctly
  1199.  * dithered at present.
  1200.  */
  1201. x = masterPtr->ditherX;
  1202. y = masterPtr->ditherY;
  1203. if (masterPtr->ditherX != 0) {
  1204.     Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y,
  1205.     masterPtr->width - x, 1);
  1206. }
  1207. if (masterPtr->ditherY < masterPtr->height) {
  1208.     x = 0;
  1209.     Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, 0,
  1210.     masterPtr->ditherY, masterPtr->width,
  1211.     masterPtr->height - masterPtr->ditherY);
  1212. }
  1213. if (y < masterPtr->height) {
  1214.     /*
  1215.      * Tell the core image code that part of the image has changed.
  1216.      */
  1217.     Tk_ImageChanged(masterPtr->tkMaster, x, y,
  1218.     (masterPtr->width - x), (masterPtr->height - y),
  1219.     masterPtr->width, masterPtr->height);
  1220. }
  1221. return TCL_OK;
  1222.     case PHOTO_TRANS: {
  1223. static CONST char *photoTransOptions[] = {
  1224.     "get", "set", (char *) NULL
  1225. };
  1226. enum transOptions {
  1227.     PHOTO_TRANS_GET, PHOTO_TRANS_SET
  1228. };
  1229. if (objc < 3) {
  1230.     Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
  1231.     return TCL_ERROR;
  1232. }
  1233. if (Tcl_GetIndexFromObj(interp, objv[2], photoTransOptions, "option",
  1234. 0, &index) != TCL_OK) {
  1235.     return TCL_ERROR;
  1236. }
  1237. switch ((enum transOptions) index) {
  1238. case PHOTO_TRANS_GET: {
  1239.     XRectangle testBox;
  1240.     TkRegion testRegion;
  1241.     if (objc != 5) {
  1242. Tcl_WrongNumArgs(interp, 3, objv, "x y");
  1243. return TCL_ERROR;
  1244.     }
  1245.     if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
  1246.     || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {
  1247. return TCL_ERROR;
  1248.     }
  1249.     if ((x < 0) || (x >= masterPtr->width)
  1250. || (y < 0) || (y >= masterPtr->height)) {
  1251. Tcl_AppendResult(interp, Tcl_GetString(objv[0]),
  1252. " transparency get: coordinates out of range",
  1253. (char *) NULL);
  1254. return TCL_ERROR;
  1255.     }
  1256.     testBox.x = x;
  1257.     testBox.y = y;
  1258.     testBox.width = 1;
  1259.     testBox.height = 1;
  1260.     /* What a way to do a test! */
  1261.     testRegion = TkCreateRegion();
  1262.     TkUnionRectWithRegion(&testBox, testRegion, testRegion);
  1263.     TkIntersectRegion(testRegion, masterPtr->validRegion, testRegion);
  1264.     TkClipBox(testRegion, &testBox);
  1265.     TkDestroyRegion(testRegion);
  1266.     Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
  1267.     (testBox.width==0 && testBox.height==0));
  1268.     return TCL_OK;
  1269. }
  1270. case PHOTO_TRANS_SET: {
  1271.     int transFlag;
  1272.     XRectangle setBox;
  1273.     if (objc != 6) {
  1274. Tcl_WrongNumArgs(interp, 3, objv, "x y boolean");
  1275. return TCL_ERROR;
  1276.     }
  1277.     if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
  1278.     || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)
  1279.     || (Tcl_GetBooleanFromObj(interp, objv[5],
  1280.     &transFlag) != TCL_OK)) {
  1281. return TCL_ERROR;
  1282.     }
  1283.     if ((x < 0) || (x >= masterPtr->width)
  1284. || (y < 0) || (y >= masterPtr->height)) {
  1285. Tcl_AppendResult(interp, Tcl_GetString(objv[0]),
  1286. " transparency set: coordinates out of range",
  1287. (char *) NULL);
  1288. return TCL_ERROR;
  1289.     }
  1290.     setBox.x = x;
  1291.     setBox.y = y;
  1292.     setBox.width = 1;
  1293.     setBox.height = 1;
  1294.     pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
  1295.     if (transFlag) {
  1296. /*
  1297.  * Make pixel transparent.
  1298.  */
  1299. TkRegion clearRegion = TkCreateRegion();
  1300. TkUnionRectWithRegion(&setBox, clearRegion, clearRegion);
  1301. TkSubtractRegion(masterPtr->validRegion, clearRegion,
  1302. masterPtr->validRegion);
  1303. TkDestroyRegion(clearRegion);
  1304. /*
  1305.  * Set the alpha value correctly.
  1306.  */
  1307. pixelPtr[3] = 0;
  1308.     } else {
  1309. /*
  1310.  * Make pixel opaque.
  1311.  */
  1312. TkUnionRectWithRegion(&setBox, masterPtr->validRegion,
  1313. masterPtr->validRegion);
  1314. pixelPtr[3] = 255;
  1315.     }
  1316.     /*
  1317.      * Inform the generic image code that the image
  1318.      * has (potentially) changed.
  1319.      */
  1320.     Tk_ImageChanged(masterPtr->tkMaster, x, y, 1, 1,
  1321.     masterPtr->width, masterPtr->height);
  1322.     masterPtr->flags &= ~IMAGE_CHANGED;
  1323.     return TCL_OK;
  1324. }
  1325. }
  1326. panic("unexpected fallthrough");
  1327.     }
  1328.     case PHOTO_WRITE: {
  1329. char *data;
  1330. Tcl_Obj *format;
  1331.         /*
  1332.          * Prevent file system access in safe interpreters.
  1333.          */
  1334.         if (Tcl_IsSafe(interp)) {
  1335.             Tcl_AppendResult(interp, "can't write image to a file in a",
  1336.     " safe interpreter", (char *) NULL);
  1337.             return TCL_ERROR;
  1338.         }
  1339.         
  1340. /*
  1341.  * photo write command - first parse and check any options given.
  1342.  */
  1343. index = 2;
  1344. memset((VOID *) &options, 0, sizeof(options));
  1345. options.name = NULL;
  1346. options.format = NULL;
  1347. if (ParseSubcommandOptions(&options, interp,
  1348. OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
  1349. &index, objc, objv) != TCL_OK) {
  1350.     return TCL_ERROR;
  1351. }
  1352. if ((options.name == NULL) || (index < objc)) {
  1353.     Tcl_WrongNumArgs(interp, 2, objv, "fileName ?options?");
  1354.     return TCL_ERROR;
  1355. }
  1356. if ((options.fromX > masterPtr->width)
  1357. || (options.fromY > masterPtr->height)
  1358. || (options.fromX2 > masterPtr->width)
  1359. || (options.fromY2 > masterPtr->height)) {
  1360.     Tcl_AppendResult(interp, "coordinates for -from option extend ",
  1361.     "outside image", (char *) NULL);
  1362.     return TCL_ERROR;
  1363. }
  1364. /*
  1365.  * Fill in default values for unspecified parameters.
  1366.  */
  1367. if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
  1368.     options.fromX2 = masterPtr->width;
  1369.     options.fromY2 = masterPtr->height;
  1370. }
  1371. /*
  1372.  * Search for an appropriate image file format handler,
  1373.  * and give an error if none is found.
  1374.  */
  1375. matched = 0;
  1376. for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
  1377. imageFormat = imageFormat->nextPtr) {
  1378.     if ((options.format == NULL)
  1379.     || (strncasecmp(Tcl_GetString(options.format),
  1380.     imageFormat->name, strlen(imageFormat->name)) == 0)) {
  1381. matched = 1;
  1382. if (imageFormat->fileWriteProc != NULL) {
  1383.     break;
  1384. }
  1385.     }
  1386. }
  1387. if (imageFormat == NULL) {
  1388.     oldformat = 1;
  1389.     for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
  1390.     imageFormat = imageFormat->nextPtr) {
  1391. if ((options.format == NULL)
  1392. || (strncasecmp(Tcl_GetString(options.format),
  1393. imageFormat->name, strlen(imageFormat->name)) == 0)) {
  1394.     matched = 1;
  1395.     if (imageFormat->fileWriteProc != NULL) {
  1396. break;
  1397.     }
  1398. }
  1399.     }
  1400. }
  1401. if (imageFormat == NULL) {
  1402.     if (options.format == NULL) {
  1403. Tcl_AppendResult(interp, "no available image file format ",
  1404. "has file writing capability", (char *) NULL);
  1405.     } else if (!matched) {
  1406. Tcl_AppendResult(interp, "image file format "",
  1407. Tcl_GetString(options.format),
  1408. "" is unknown", (char *) NULL);
  1409.     } else {
  1410. Tcl_AppendResult(interp, "image file format "",
  1411. Tcl_GetString(options.format),
  1412. "" has no file writing capability",
  1413. (char *) NULL);
  1414.     }
  1415.     return TCL_ERROR;
  1416. }
  1417. /*
  1418.  * Call the handler's file write procedure to write out
  1419.  * the image.
  1420.  */
  1421. data = ImgGetPhoto(masterPtr, &block, &options);
  1422. format = options.format;
  1423. if (oldformat && format) {
  1424.     format = (Tcl_Obj *) Tcl_GetString(options.format);
  1425. }
  1426. result = (*imageFormat->fileWriteProc)(interp,
  1427. Tcl_GetString(options.name), format, &block);
  1428. if (options.background) {
  1429.     Tk_FreeColor(options.background);
  1430. }
  1431. if (data) {
  1432.     ckfree(data);
  1433. }
  1434. return result;
  1435.     }
  1436.     }
  1437.     panic("unexpected fallthrough");
  1438.     return TCL_ERROR; /* NOT REACHED */
  1439. }
  1440. /*
  1441.  *----------------------------------------------------------------------
  1442.  *
  1443.  * ParseSubcommandOptions --
  1444.  *
  1445.  * This procedure is invoked to process one of the options
  1446.  * which may be specified for the photo image subcommands,
  1447.  * namely, -from, -to, -zoom, -subsample, -format, -shrink,
  1448.  * and -compositingrule.
  1449.  *
  1450.  * Results:
  1451.  * A standard Tcl result.
  1452.  *
  1453.  * Side effects:
  1454.  * Fields in *optPtr get filled in.
  1455.  *
  1456.  *----------------------------------------------------------------------
  1457.  */
  1458. static int
  1459. ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv)
  1460.     struct SubcommandOptions *optPtr;
  1461. /* Information about the options specified
  1462.  * and the values given is returned here. */
  1463.     Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
  1464.     int allowedOptions; /* Indicates which options are valid for
  1465.  * the current command. */
  1466.     int *optIndexPtr; /* Points to a variable containing the
  1467.  * current index in objv; this variable is
  1468.  * updated by this procedure. */
  1469.     int objc; /* Number of arguments in objv[]. */
  1470.     Tcl_Obj *CONST objv[]; /* Arguments to be parsed. */
  1471. {
  1472.     int index, c, bit, currentBit;
  1473.     int length;
  1474.     char *option, **listPtr;
  1475.     int values[4];
  1476.     int numValues, maxValues, argIndex;
  1477.     for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) {
  1478. /*
  1479.  * We can have one value specified without an option;
  1480.  * it goes into optPtr->name.
  1481.  */
  1482. option = Tcl_GetStringFromObj(objv[index], &length);
  1483. if (option[0] != '-') {
  1484.     if (optPtr->name == NULL) {
  1485. optPtr->name = objv[index];
  1486. continue;
  1487.     }
  1488.     break;
  1489. }
  1490. /*
  1491.  * Work out which option this is.
  1492.  */
  1493. c = option[0];
  1494. bit = 0;
  1495. currentBit = 1;
  1496. for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {
  1497.     if ((c == *listPtr[0])
  1498.     && (strncmp(option, *listPtr, (size_t) length) == 0)) {
  1499. if (bit != 0) {
  1500.     bit = 0; /* An ambiguous option. */
  1501.     break;
  1502. }
  1503. bit = currentBit;
  1504.     }
  1505.     currentBit <<= 1;
  1506. }
  1507. /*
  1508.  * If this option is not recognized and allowed, put
  1509.  * an error message in the interpreter and return.
  1510.  */
  1511. if ((allowedOptions & bit) == 0) {
  1512.     Tcl_AppendResult(interp, "unrecognized option "",
  1513.          Tcl_GetString(objv[index]),
  1514.     "": must be ", (char *)NULL);
  1515.     bit = 1;
  1516.     for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {
  1517. if ((allowedOptions & bit) != 0) {
  1518.     if ((allowedOptions & (bit - 1)) != 0) {
  1519. Tcl_AppendResult(interp, ", ", (char *) NULL);
  1520. if ((allowedOptions & ~((bit << 1) - 1)) == 0) {
  1521.     Tcl_AppendResult(interp, "or ", (char *) NULL);
  1522. }
  1523.     }
  1524.     Tcl_AppendResult(interp, *listPtr, (char *) NULL);
  1525. }
  1526. bit <<= 1;
  1527.     }
  1528.     return TCL_ERROR;
  1529. }
  1530. /*
  1531.  * For the -from, -to, -zoom and -subsample options,
  1532.  * parse the values given.  Report an error if too few
  1533.  * or too many values are given.
  1534.  */
  1535. if (bit == OPT_BACKGROUND) {
  1536.     /*
  1537.      * The -background option takes a single XColor value.
  1538.      */
  1539.     if (index + 1 < objc) {
  1540. *optIndexPtr = ++index;
  1541. optPtr->background = Tk_GetColor(interp, Tk_MainWindow(interp),
  1542. Tk_GetUid(Tcl_GetString(objv[index])));
  1543. if (!optPtr->background) {
  1544.     return TCL_ERROR;
  1545. }
  1546.     } else {
  1547. Tcl_AppendResult(interp, "the "-background" option ",
  1548. "requires a value", (char *) NULL);
  1549. return TCL_ERROR;
  1550.     }
  1551. } else if (bit == OPT_FORMAT) {
  1552.     /*
  1553.      * The -format option takes a single string value.  Note
  1554.      * that parsing this is outside the scope of this
  1555.      * function.
  1556.      */
  1557.     if (index + 1 < objc) {
  1558. *optIndexPtr = ++index;
  1559. optPtr->format = objv[index];
  1560.     } else {
  1561. Tcl_AppendResult(interp, "the "-format" option ",
  1562. "requires a value", (char *) NULL);
  1563. return TCL_ERROR;
  1564.     }
  1565. } else if (bit == OPT_COMPOSITE) {
  1566.     /*
  1567.      * The -compositingrule option takes a single value from
  1568.      * a well-known set.
  1569.      */
  1570.     if (index + 1 < objc) {
  1571. /*
  1572.  * Note that these must match the TK_PHOTO_COMPOSITE_*
  1573.  * constants.
  1574.  */
  1575. static CONST char *compositingRules[] = {
  1576.     "overlay", "set",
  1577.     NULL
  1578. };
  1579. index++;
  1580. if (Tcl_GetIndexFromObj(interp, objv[index], compositingRules,
  1581. "compositing rule", 0, &optPtr->compositingRule)
  1582. != TCL_OK) {
  1583.     return TCL_ERROR;
  1584. }
  1585. *optIndexPtr = index;
  1586.     } else {
  1587. Tcl_AppendResult(interp, "the "-compositingrule" option ",
  1588. "requires a value", (char *) NULL);
  1589. return TCL_ERROR;
  1590.     }
  1591. } else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) {
  1592.     char *val;
  1593.     maxValues = ((bit == OPT_FROM) || (bit == OPT_TO))? 4: 2;
  1594.     argIndex = index + 1;
  1595.     for (numValues = 0; numValues < maxValues; ++numValues) {
  1596. if (argIndex >= objc) {
  1597.     break;
  1598. }
  1599.         val = Tcl_GetString(objv[argIndex]);
  1600. if ((argIndex < objc) && (isdigit(UCHAR(val[0]))
  1601. || ((val[0] == '-') && isdigit(UCHAR(val[1]))))) {
  1602.     if (Tcl_GetInt(interp, val, &values[numValues])
  1603.     != TCL_OK) {
  1604. return TCL_ERROR;
  1605.     }
  1606. } else {
  1607.     break;
  1608. }
  1609. ++argIndex;
  1610.     }
  1611.     if (numValues == 0) {
  1612. Tcl_AppendResult(interp, "the "", option, "" option ",
  1613.  "requires one ", maxValues == 2? "or two": "to four",
  1614.  " integer values", (char *) NULL);
  1615. return TCL_ERROR;
  1616.     }
  1617.     *optIndexPtr = (index += numValues);
  1618.     /*
  1619.      * Y values default to the corresponding X value if not specified.
  1620.      */
  1621.     if (numValues == 1) {
  1622. values[1] = values[0];
  1623.     }
  1624.     if (numValues == 3) {
  1625. values[3] = values[2];
  1626.     }
  1627.     /*
  1628.      * Check the values given and put them in the appropriate
  1629.      * field of the SubcommandOptions structure.
  1630.      */
  1631.     switch (bit) {
  1632. case OPT_FROM:
  1633.     if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2)
  1634.     && ((values[2] < 0) || (values[3] < 0)))) {
  1635. Tcl_AppendResult(interp, "value(s) for the -from",
  1636. " option must be non-negative", (char *) NULL);
  1637. return TCL_ERROR;
  1638.     }
  1639.     if (numValues <= 2) {
  1640. optPtr->fromX = values[0];
  1641. optPtr->fromY = values[1];
  1642. optPtr->fromX2 = -1;
  1643. optPtr->fromY2 = -1;
  1644.     } else {
  1645. optPtr->fromX = MIN(values[0], values[2]);
  1646. optPtr->fromY = MIN(values[1], values[3]);
  1647. optPtr->fromX2 = MAX(values[0], values[2]);
  1648. optPtr->fromY2 = MAX(values[1], values[3]);
  1649.     }
  1650.     break;
  1651. case OPT_SUBSAMPLE:
  1652.     optPtr->subsampleX = values[0];
  1653.     optPtr->subsampleY = values[1];
  1654.     break;
  1655. case OPT_TO:
  1656.     if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2)
  1657.     && ((values[2] < 0) || (values[3] < 0)))) {
  1658. Tcl_AppendResult(interp, "value(s) for the -to",
  1659. " option must be non-negative", (char *) NULL);
  1660. return TCL_ERROR;
  1661.     }
  1662.     if (numValues <= 2) {
  1663. optPtr->toX = values[0];
  1664. optPtr->toY = values[1];
  1665. optPtr->toX2 = -1;
  1666. optPtr->toY2 = -1;
  1667.     } else {
  1668. optPtr->toX = MIN(values[0], values[2]);
  1669. optPtr->toY = MIN(values[1], values[3]);
  1670. optPtr->toX2 = MAX(values[0], values[2]);
  1671. optPtr->toY2 = MAX(values[1], values[3]);
  1672.     }
  1673.     break;
  1674. case OPT_ZOOM:
  1675.     if ((values[0] <= 0) || (values[1] <= 0)) {
  1676. Tcl_AppendResult(interp, "value(s) for the -zoom",
  1677. " option must be positive", (char *) NULL);
  1678. return TCL_ERROR;
  1679.     }
  1680.     optPtr->zoomX = values[0];
  1681.     optPtr->zoomY = values[1];
  1682.     break;
  1683.     }
  1684. }
  1685. /*
  1686.  * Remember that we saw this option.
  1687.  */
  1688. optPtr->options |= bit;
  1689.     }
  1690.     return TCL_OK;
  1691. }
  1692. /*
  1693.  *----------------------------------------------------------------------
  1694.  *
  1695.  * ImgPhotoConfigureMaster --
  1696.  *
  1697.  * This procedure is called when a photo image is created or
  1698.  * reconfigured.  It processes configuration options and resets
  1699.  * any instances of the image.
  1700.  *
  1701.  * Results:
  1702.  * A standard Tcl return value.  If TCL_ERROR is returned then
  1703.  * an error message is left in the masterPtr->interp's result.
  1704.  *
  1705.  * Side effects:
  1706.  * Existing instances of the image will be redisplayed to match
  1707.  * the new configuration options.
  1708.  *
  1709.  *----------------------------------------------------------------------
  1710.  */
  1711. static int
  1712. ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags)
  1713.     Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
  1714.     PhotoMaster *masterPtr; /* Pointer to data structure describing
  1715.  * overall photo image to (re)configure. */
  1716.     int objc; /* Number of entries in objv. */
  1717.     Tcl_Obj *CONST objv[]; /* Pairs of configuration options for image. */
  1718.     int flags; /* Flags to pass to Tk_ConfigureWidget,
  1719.  * such as TK_CONFIG_ARGV_ONLY. */
  1720. {
  1721.     PhotoInstance *instancePtr;
  1722.     CONST char *oldFileString, *oldPaletteString;
  1723.     Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL;
  1724.     int length, i, j;
  1725.     double oldGamma;
  1726.     int result;
  1727.     Tcl_Channel chan;
  1728.     Tk_PhotoImageFormat *imageFormat;
  1729.     int imageWidth, imageHeight;
  1730.     CONST char **args;
  1731.     int oldformat;
  1732.     Tcl_Obj *tempdata, *tempformat;
  1733.     args = (CONST char **) ckalloc((objc + 1) * sizeof(char *));
  1734.     for (i = 0, j = 0; i < objc; i++,j++) {
  1735. args[j] = Tcl_GetStringFromObj(objv[i], &length);
  1736. if ((length > 1) && (args[j][0] == '-')) {
  1737.     if ((args[j][1] == 'd') &&
  1738.     !strncmp(args[j], "-data", (size_t) length)) {
  1739. if (++i < objc) {
  1740.     data = objv[i];
  1741.     j--;
  1742. } else {
  1743.     Tcl_AppendResult(interp,
  1744.     "value for "-data" missing", (char *) NULL);
  1745.     return TCL_ERROR;
  1746. }
  1747.     } else if ((args[j][1] == 'f') &&
  1748.     !strncmp(args[j], "-format", (size_t) length)) {
  1749. if (++i < objc) {
  1750.     format = objv[i];
  1751.     j--;
  1752. } else {
  1753.     Tcl_AppendResult(interp,
  1754.     "value for "-format" missing", (char *) NULL);
  1755.     return TCL_ERROR;
  1756. }
  1757.     }
  1758. }
  1759.     }
  1760.     /*
  1761.      * Save the current values for fileString and dataString, so we
  1762.      * can tell if the user specifies them anew.
  1763.      * IMPORTANT: if the format changes we have to interpret
  1764.      * "-file" and "-data" again as well!!!!!!! It might be
  1765.      * that the format string influences how "-data" or "-file"
  1766.      * is interpreted.
  1767.      */
  1768.     oldFileString = masterPtr->fileString;
  1769.     if (oldFileString == NULL) {
  1770. oldData = masterPtr->dataString;
  1771. if (oldData != NULL) {
  1772.     Tcl_IncrRefCount(oldData);
  1773. }
  1774.     } else {
  1775. oldData = NULL;
  1776.     }
  1777.     oldFormat = masterPtr->format;
  1778.     if (oldFormat != NULL) {
  1779. Tcl_IncrRefCount(oldFormat);
  1780.     }
  1781.     oldPaletteString = masterPtr->palette;
  1782.     oldGamma = masterPtr->gamma;
  1783.     /*
  1784.      * Process the configuration options specified.
  1785.      */
  1786.     if (Tk_ConfigureWidget(interp, Tk_MainWindow(interp), configSpecs,
  1787.     j, args, (char *) masterPtr, flags) != TCL_OK) {
  1788. ckfree((char *) args);
  1789. goto errorExit;
  1790.     }
  1791.     ckfree((char *) args);
  1792.     /*
  1793.      * Regard the empty string for -file, -data or -format as the null
  1794.      * value.
  1795.      */
  1796.     if ((masterPtr->fileString != NULL) && (masterPtr->fileString[0] == 0)) {
  1797. ckfree(masterPtr->fileString);
  1798. masterPtr->fileString = NULL;
  1799.     }
  1800.     if (data) {
  1801. /*
  1802.  * Force into ByteArray format, which most (all) image handlers
  1803.  * will use anyway.  Empty length means ignore the -data option.
  1804.  */
  1805. (void) Tcl_GetByteArrayFromObj(data, &length);
  1806. if (length) {
  1807.     Tcl_IncrRefCount(data);
  1808. } else {
  1809.     data = NULL;
  1810. }
  1811. if (masterPtr->dataString) {
  1812.     Tcl_DecrRefCount(masterPtr->dataString);
  1813. }
  1814. masterPtr->dataString = data;
  1815.     }
  1816.     if (format) {
  1817. /*
  1818.  * Stringify to ignore -format "".  It may come in as a list or
  1819.  * other object.
  1820.  */
  1821. (void) Tcl_GetStringFromObj(format, &length);
  1822. if (length) {
  1823.     Tcl_IncrRefCount(format);
  1824. } else {
  1825.     format = NULL;
  1826. }
  1827. if (masterPtr->format) {
  1828.     Tcl_DecrRefCount(masterPtr->format);
  1829. }
  1830. masterPtr->format = format;
  1831.     }
  1832.     /*
  1833.      * Set the image to the user-requested size, if any,
  1834.      * and make sure storage is correctly allocated for this image.
  1835.      */
  1836.     if (ImgPhotoSetSize(masterPtr, masterPtr->width,
  1837.     masterPtr->height) != TCL_OK) {
  1838. Tcl_ResetResult(interp);
  1839. Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1840. TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
  1841. goto errorExit;
  1842.     }
  1843.     /*
  1844.      * Read in the image from the file or string if the user has
  1845.      * specified the -file or -data option.
  1846.      */
  1847.     if ((masterPtr->fileString != NULL)
  1848.     && ((masterPtr->fileString != oldFileString)
  1849.     || (masterPtr->format != oldFormat))) {
  1850.         /*
  1851.          * Prevent file system access in a safe interpreter.
  1852.          */
  1853.         if (Tcl_IsSafe(interp)) {
  1854.     Tcl_ResetResult(interp);
  1855.             Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1856.     "can't get image from a file in a safe interpreter",
  1857.     (char *) NULL);
  1858.     goto errorExit;
  1859.         }
  1860.         
  1861. chan = Tcl_OpenFileChannel(interp, masterPtr->fileString, "r", 0);
  1862. if (chan == NULL) {
  1863.     goto errorExit;
  1864. }
  1865. /*
  1866.  * -translation binary also sets -encoding binary
  1867.  */
  1868.         if ((Tcl_SetChannelOption(interp, chan,
  1869. "-translation", "binary") != TCL_OK) ||
  1870. (MatchFileFormat(interp, chan, masterPtr->fileString,
  1871. masterPtr->format, &imageFormat, &imageWidth,
  1872. &imageHeight, &oldformat) != TCL_OK)) {
  1873.     Tcl_Close(NULL, chan);
  1874.     goto errorExit;
  1875. }
  1876. result = ImgPhotoSetSize(masterPtr, imageWidth, imageHeight);
  1877. if (result != TCL_OK) {
  1878.     Tcl_Close(NULL, chan);
  1879.     Tcl_ResetResult(interp);
  1880.     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1881.     TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
  1882.     goto errorExit;
  1883. }
  1884. tempformat = masterPtr->format;
  1885. if (oldformat && tempformat) {
  1886.     tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
  1887. }
  1888. result = (*imageFormat->fileReadProc)(interp, chan,
  1889. masterPtr->fileString, tempformat,
  1890. (Tk_PhotoHandle) masterPtr, 0, 0,
  1891. imageWidth, imageHeight, 0, 0);
  1892. Tcl_Close(NULL, chan);
  1893. if (result != TCL_OK) {
  1894.     goto errorExit;
  1895. }
  1896. Tcl_ResetResult(interp);
  1897. masterPtr->flags |= IMAGE_CHANGED;
  1898.     }
  1899.     if ((masterPtr->fileString == NULL) && (masterPtr->dataString != NULL)
  1900.     && ((masterPtr->dataString != oldData)
  1901.     || (masterPtr->format != oldFormat))) {
  1902. if (MatchStringFormat(interp, masterPtr->dataString,
  1903. masterPtr->format, &imageFormat, &imageWidth,
  1904. &imageHeight, &oldformat) != TCL_OK) {
  1905.     goto errorExit;
  1906. }
  1907. if (ImgPhotoSetSize(masterPtr, imageWidth, imageHeight) != TCL_OK) {
  1908.     Tcl_ResetResult(interp);
  1909.     Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  1910.     TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
  1911.     goto errorExit;
  1912. }
  1913. tempformat = masterPtr->format;
  1914. tempdata = masterPtr->dataString;
  1915. if (oldformat) {
  1916.     if (tempformat) {
  1917. tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
  1918.     }
  1919.     tempdata = (Tcl_Obj *) Tcl_GetString(tempdata);
  1920. }
  1921. if ((*imageFormat->stringReadProc)(interp, tempdata,
  1922. tempformat, (Tk_PhotoHandle) masterPtr,
  1923. 0, 0, imageWidth, imageHeight, 0, 0) != TCL_OK) {
  1924.     goto errorExit;
  1925. }
  1926. Tcl_ResetResult(interp);
  1927. masterPtr->flags |= IMAGE_CHANGED;
  1928.     }
  1929.     /*
  1930.      * Enforce a reasonable value for gamma.
  1931.      */
  1932.     if (masterPtr->gamma <= 0) {
  1933. masterPtr->gamma = 1.0;
  1934.     }
  1935.     if ((masterPtr->gamma != oldGamma)
  1936.     || (masterPtr->palette != oldPaletteString)) {
  1937. masterPtr->flags |= IMAGE_CHANGED;
  1938.     }
  1939.     /*
  1940.      * Cycle through all of the instances of this image, regenerating
  1941.      * the information for each instance.  Then force the image to be
  1942.      * redisplayed everywhere that it is used.
  1943.      */
  1944.     for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
  1945.     instancePtr = instancePtr->nextPtr) {
  1946. ImgPhotoConfigureInstance(instancePtr);
  1947.     }
  1948.     /*
  1949.      * Inform the generic image code that the image
  1950.      * has (potentially) changed.
  1951.      */
  1952.     Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
  1953.     masterPtr->height, masterPtr->width, masterPtr->height);
  1954.     masterPtr->flags &= ~IMAGE_CHANGED;
  1955.     if (oldData != NULL) {
  1956. Tcl_DecrRefCount(oldData);
  1957.     }
  1958.     if (oldFormat != NULL) {
  1959. Tcl_DecrRefCount(oldFormat);
  1960.     }
  1961.     ToggleComplexAlphaIfNeeded(masterPtr);
  1962.     return TCL_OK;
  1963.   errorExit:
  1964.     if (oldData != NULL) {
  1965. Tcl_DecrRefCount(oldData);
  1966.     }
  1967.     if (oldFormat != NULL) {
  1968. Tcl_DecrRefCount(oldFormat);
  1969.     }
  1970.     return TCL_ERROR;
  1971. }
  1972. /*
  1973.  *----------------------------------------------------------------------
  1974.  *
  1975.  * ImgPhotoConfigureInstance --
  1976.  *
  1977.  * This procedure is called to create displaying information for
  1978.  * a photo image instance based on the configuration information
  1979.  * in the master.  It is invoked both when new instances are
  1980.  * created and when the master is reconfigured.
  1981.  *
  1982.  * Results:
  1983.  * None.
  1984.  *
  1985.  * Side effects:
  1986.  * Generates errors via Tcl_BackgroundError if there are problems
  1987.  * in setting up the instance.
  1988.  *
  1989.  *----------------------------------------------------------------------
  1990.  */
  1991. static void
  1992. ImgPhotoConfigureInstance(instancePtr)
  1993.     PhotoInstance *instancePtr; /* Instance to reconfigure. */
  1994. {
  1995.     PhotoMaster *masterPtr = instancePtr->masterPtr;
  1996.     XImage *imagePtr;
  1997.     int bitsPerPixel;
  1998.     ColorTable *colorTablePtr;
  1999.     XRectangle validBox;
  2000.     /*
  2001.      * If the -palette configuration option has been set for the master,
  2002.      * use the value specified for our palette, but only if it is
  2003.      * a valid palette for our windows.  Use the gamma value specified
  2004.      * the master.
  2005.      */
  2006.     if ((masterPtr->palette && masterPtr->palette[0])
  2007.     && IsValidPalette(instancePtr, masterPtr->palette)) {
  2008. instancePtr->palette = masterPtr->palette;
  2009.     } else {
  2010. instancePtr->palette = instancePtr->defaultPalette;
  2011.     }
  2012.     instancePtr->gamma = masterPtr->gamma;
  2013.     /*
  2014.      * If we don't currently have a color table, or if the one we
  2015.      * have no longer applies (e.g. because our palette or gamma
  2016.      * has changed), get a new one.
  2017.      */
  2018.     colorTablePtr = instancePtr->colorTablePtr;
  2019.     if ((colorTablePtr == NULL)
  2020.     || (instancePtr->colormap != colorTablePtr->id.colormap)
  2021.     || (instancePtr->palette != colorTablePtr->id.palette)
  2022.     || (instancePtr->gamma != colorTablePtr->id.gamma)) {
  2023. /*
  2024.  * Free up our old color table, and get a new one.
  2025.  */
  2026. if (colorTablePtr != NULL) {
  2027.     colorTablePtr->liveRefCount -= 1;
  2028.     FreeColorTable(colorTablePtr, 0);
  2029. }
  2030. GetColorTable(instancePtr);
  2031. /*
  2032.  * Create a new XImage structure for sending data to
  2033.  * the X server, if necessary.
  2034.  */
  2035. if (instancePtr->colorTablePtr->flags & BLACK_AND_WHITE) {
  2036.     bitsPerPixel = 1;
  2037. } else {
  2038.     bitsPerPixel = instancePtr->visualInfo.depth;
  2039. }
  2040. if ((instancePtr->imagePtr == NULL)
  2041. || (instancePtr->imagePtr->bits_per_pixel != bitsPerPixel)) {
  2042.     if (instancePtr->imagePtr != NULL) {
  2043. XDestroyImage(instancePtr->imagePtr);
  2044.     }
  2045.     imagePtr = XCreateImage(instancePtr->display,
  2046.     instancePtr->visualInfo.visual, (unsigned) bitsPerPixel,
  2047.     (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, (char *) NULL,
  2048.     1, 1, 32, 0);
  2049.     instancePtr->imagePtr = imagePtr;
  2050.     /*
  2051.      * We create images using the local host's endianness, rather than
  2052.      * the endianness of the server; otherwise we would have to
  2053.      * byte-swap any 16 or 32 bit values that we store in the image
  2054.      * if the server's endianness is different from ours.
  2055.      */
  2056.     if (imagePtr != NULL) {
  2057. #ifdef WORDS_BIGENDIAN
  2058. imagePtr->byte_order = MSBFirst;
  2059. #else
  2060. imagePtr->byte_order = LSBFirst;
  2061. #endif
  2062. _XInitImageFuncPtrs(imagePtr);
  2063.     }
  2064. }
  2065.     }
  2066.     /*
  2067.      * If the user has specified a width and/or height for the master
  2068.      * which is different from our current width/height, set the size
  2069.      * to the values specified by the user.  If we have no pixmap, we
  2070.      * do this also, since it has the side effect of allocating a
  2071.      * pixmap for us.
  2072.      */
  2073.     if ((instancePtr->pixels == None) || (instancePtr->error == NULL)
  2074.     || (instancePtr->width != masterPtr->width)
  2075.     || (instancePtr->height != masterPtr->height)) {
  2076. ImgPhotoInstanceSetSize(instancePtr);
  2077.     }
  2078.     /*
  2079.      * Redither this instance if necessary.
  2080.      */
  2081.     if ((masterPtr->flags & IMAGE_CHANGED)
  2082.     || (instancePtr->colorTablePtr != colorTablePtr)) {
  2083. TkClipBox(masterPtr->validRegion, &validBox);
  2084. if ((validBox.width > 0) && (validBox.height > 0)) {
  2085.     DitherInstance(instancePtr, validBox.x, validBox.y,
  2086.     validBox.width, validBox.height);
  2087. }
  2088.     }
  2089. }
  2090. /*
  2091.  *----------------------------------------------------------------------
  2092.  *
  2093.  * ImgPhotoGet --
  2094.  *
  2095.  * This procedure is called for each use of a photo image in a
  2096.  * widget.
  2097.  *
  2098.  * Results:
  2099.  * The return value is a token for the instance, which is passed
  2100.  * back to us in calls to ImgPhotoDisplay and ImgPhotoFree.
  2101.  *
  2102.  * Side effects:
  2103.  * A data structure is set up for the instance (or, an existing
  2104.  * instance is re-used for the new one).
  2105.  *
  2106.  *----------------------------------------------------------------------
  2107.  */
  2108. static ClientData
  2109. ImgPhotoGet(tkwin, masterData)
  2110.     Tk_Window tkwin; /* Window in which the instance will be
  2111.  * used. */
  2112.     ClientData masterData; /* Pointer to our master structure for the
  2113.  * image. */
  2114. {
  2115.     PhotoMaster *masterPtr = (PhotoMaster *) masterData;
  2116.     PhotoInstance *instancePtr;
  2117.     Colormap colormap;
  2118.     int mono, nRed, nGreen, nBlue;
  2119.     XVisualInfo visualInfo, *visInfoPtr;
  2120.     char buf[TCL_INTEGER_SPACE * 3];
  2121.     int numVisuals;
  2122.     XColor *white, *black;
  2123.     XGCValues gcValues;
  2124.     /*
  2125.      * Table of "best" choices for palette for PseudoColor displays
  2126.      * with between 3 and 15 bits/pixel.
  2127.      */
  2128.     static int paletteChoice[13][3] = {
  2129. /*  #red, #green, #blue */
  2130.  {2,  2,  2, /* 3 bits, 8 colors */},
  2131.  {2,  3,  2, /* 4 bits, 12 colors */},
  2132.  {3,  4,  2, /* 5 bits, 24 colors */},
  2133.  {4,  5,  3, /* 6 bits, 60 colors */},
  2134.  {5,  6,  4, /* 7 bits, 120 colors */},
  2135.  {7,  7,  4, /* 8 bits, 198 colors */},
  2136.  {8, 10,  6, /* 9 bits, 480 colors */},
  2137. {10, 12,  8, /* 10 bits, 960 colors */},
  2138. {14, 15,  9, /* 11 bits, 1890 colors */},
  2139. {16, 20, 12, /* 12 bits, 3840 colors */},
  2140. {20, 24, 16, /* 13 bits, 7680 colors */},
  2141. {26, 30, 20, /* 14 bits, 15600 colors */},
  2142. {32, 32, 30, /* 15 bits, 30720 colors */}
  2143.     };
  2144.     /*
  2145.      * See if there is already an instance for windows using
  2146.      * the same colormap.  If so then just re-use it.
  2147.      */
  2148.     colormap = Tk_Colormap(tkwin);
  2149.     for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
  2150.     instancePtr = instancePtr->nextPtr) {
  2151. if ((colormap == instancePtr->colormap)
  2152. && (Tk_Display(tkwin) == instancePtr->display)) {
  2153.     /*
  2154.      * Re-use this instance.
  2155.      */
  2156.     if (instancePtr->refCount == 0) {
  2157. /*
  2158.  * We are resurrecting this instance.
  2159.  */
  2160. Tcl_CancelIdleCall(DisposeInstance, (ClientData) instancePtr);
  2161. if (instancePtr->colorTablePtr != NULL) {
  2162.     FreeColorTable(instancePtr->colorTablePtr, 0);
  2163. }
  2164. GetColorTable(instancePtr);
  2165.     }
  2166.     instancePtr->refCount++;
  2167.     return (ClientData) instancePtr;
  2168. }
  2169.     }
  2170.     /*
  2171.      * The image isn't already in use in a window with the same colormap.
  2172.      * Make a new instance of the image.
  2173.      */
  2174.     instancePtr = (PhotoInstance *) ckalloc(sizeof(PhotoInstance));
  2175.     instancePtr->masterPtr = masterPtr;
  2176.     instancePtr->display = Tk_Display(tkwin);
  2177.     instancePtr->colormap = Tk_Colormap(tkwin);
  2178.     Tk_PreserveColormap(instancePtr->display, instancePtr->colormap);
  2179.     instancePtr->refCount = 1;
  2180.     instancePtr->colorTablePtr = NULL;
  2181.     instancePtr->pixels = None;
  2182.     instancePtr->error = NULL;
  2183.     instancePtr->width = 0;
  2184.     instancePtr->height = 0;
  2185.     instancePtr->imagePtr = 0;
  2186.     instancePtr->nextPtr = masterPtr->instancePtr;
  2187.     masterPtr->instancePtr = instancePtr;
  2188.     /*
  2189.      * Obtain information about the visual and decide on the
  2190.      * default palette.
  2191.      */
  2192.     visualInfo.screen = Tk_ScreenNumber(tkwin);
  2193.     visualInfo.visualid = XVisualIDFromVisual(Tk_Visual(tkwin));
  2194.     visInfoPtr = XGetVisualInfo(Tk_Display(tkwin),
  2195.     VisualScreenMask | VisualIDMask, &visualInfo, &numVisuals);
  2196.     nRed = 2;
  2197.     nGreen = nBlue = 0;
  2198.     mono = 1;
  2199.     if (visInfoPtr != NULL) {
  2200. instancePtr->visualInfo = *visInfoPtr;
  2201. switch (visInfoPtr->class) {
  2202.     case DirectColor:
  2203.     case TrueColor:
  2204. nRed = 1 << CountBits(visInfoPtr->red_mask);
  2205. nGreen = 1 << CountBits(visInfoPtr->green_mask);
  2206. nBlue = 1 << CountBits(visInfoPtr->blue_mask);
  2207. mono = 0;
  2208. break;
  2209.     case PseudoColor:
  2210.     case StaticColor:
  2211. if (visInfoPtr->depth > 15) {
  2212.     nRed = 32;
  2213.     nGreen = 32;
  2214.     nBlue = 32;
  2215.     mono = 0;
  2216. } else if (visInfoPtr->depth >= 3) {
  2217.     int *ip = paletteChoice[visInfoPtr->depth - 3];
  2218.     
  2219.     nRed = ip[0];
  2220.     nGreen = ip[1];
  2221.     nBlue = ip[2];
  2222.     mono = 0;
  2223. }
  2224. break;
  2225.     case GrayScale:
  2226.     case StaticGray:
  2227. nRed = 1 << visInfoPtr->depth;
  2228. break;
  2229. }
  2230. XFree((char *) visInfoPtr);
  2231.     } else {
  2232. panic("ImgPhotoGet couldn't find visual for window");
  2233.     }
  2234.     sprintf(buf, ((mono) ? "%d": "%d/%d/%d"), nRed, nGreen, nBlue);
  2235.     instancePtr->defaultPalette = Tk_GetUid(buf);
  2236.     /*
  2237.      * Make a GC with background = black and foreground = white.
  2238.      */
  2239.     white = Tk_GetColor(masterPtr->interp, tkwin, "white");
  2240.     black = Tk_GetColor(masterPtr->interp, tkwin, "black");
  2241.     gcValues.foreground = (white != NULL)? white->pixel:
  2242.     WhitePixelOfScreen(Tk_Screen(tkwin));
  2243.     gcValues.background = (black != NULL)? black->pixel:
  2244.     BlackPixelOfScreen(Tk_Screen(tkwin));
  2245.     gcValues.graphics_exposures = False;
  2246.     instancePtr->gc = Tk_GetGC(tkwin,
  2247.     GCForeground|GCBackground|GCGraphicsExposures, &gcValues);
  2248.     /*
  2249.      * Set configuration options and finish the initialization of the instance.
  2250.      * This will also dither the image if necessary.
  2251.      */
  2252.     ImgPhotoConfigureInstance(instancePtr);
  2253.     /*
  2254.      * If this is the first instance, must set the size of the image.
  2255.      */
  2256.     if (instancePtr->nextPtr == NULL) {
  2257. Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
  2258. masterPtr->width, masterPtr->height);
  2259.     }
  2260.     return (ClientData) instancePtr;
  2261. }
  2262. /*
  2263.  *----------------------------------------------------------------------
  2264.  *
  2265.  * ToggleComplexAlphaIfNeeded --
  2266.  *
  2267.  * This procedure is called when an image is modified to
  2268.  * check if any partially transparent pixels exist, which
  2269.  * requires blending instead of straight copy.
  2270.  *
  2271.  * Results:
  2272.  * None.
  2273.  *
  2274.  * Side effects:
  2275.  * (Re)sets COMPLEX_ALPHA flag of master.
  2276.  *
  2277.  *----------------------------------------------------------------------
  2278.  */
  2279. static int
  2280. ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr)
  2281. {
  2282.     size_t len = MAX(mPtr->userWidth, mPtr->width) *
  2283. MAX(mPtr->userHeight, mPtr->height) * 4;
  2284.     unsigned char *c   = mPtr->pix32;
  2285.     unsigned char *end = c + len;
  2286.     /*
  2287.      * Set the COMPLEX_ALPHA flag if we have an image with partially
  2288.      * transparent bits.
  2289.      */
  2290.     mPtr->flags &= ~COMPLEX_ALPHA;
  2291.     c += 3; /* start at first alpha byte */
  2292.     for (; c < end; c += 4) {
  2293. if (*c && *c != 255) {
  2294.           mPtr->flags |= COMPLEX_ALPHA;
  2295.     break;
  2296. }
  2297.     }
  2298.     return (mPtr->flags & COMPLEX_ALPHA);
  2299. }
  2300. /*
  2301.  *----------------------------------------------------------------------
  2302.  *
  2303.  * ImgPhotoBlendComplexAlpha --
  2304.  *
  2305.  * This procedure is called when an image with partially
  2306.  * transparent pixels must be drawn over another image.
  2307.  *
  2308.  * Results:
  2309.  * None.
  2310.  *
  2311.  * Side effects:
  2312.  * Background image passed in gets drawn over with image data.
  2313.  *
  2314.  *----------------------------------------------------------------------
  2315.  */
  2316. /*
  2317.  * This should work on all platforms that set mask and shift data properly
  2318.  * from the visualInfo.
  2319.  * RGB is really only a 24+ bpp version whereas RGB15 is the correct version
  2320.  * and works for 15bpp+, but it slower, so it's only used for 15bpp+.
  2321.  *
  2322.  * Note that Win32 pre-defines those operations that we really need.
  2323.  */
  2324. #ifndef __WIN32__
  2325. #define GetRValue(rgb) (UCHAR((rgb & red_mask) >> red_shift))
  2326. #define GetGValue(rgb) (UCHAR((rgb & green_mask) >> green_shift))
  2327. #define GetBValue(rgb) (UCHAR((rgb & blue_mask) >> blue_shift))
  2328. #define RGB(r,g,b)      ((unsigned)((UCHAR(r)<<red_shift)|(UCHAR(g)<<green_shift)|(UCHAR(b)<<blue_shift)))
  2329. #define RGB15(r,g,b)    ((unsigned)(((r*red_mask/255)&red_mask)|((g*green_mask/255)&green_mask)|((b*blue_mask/255)&blue_mask)))
  2330. #endif /* !__WIN32__ */
  2331. static void
  2332. ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height)
  2333.     XImage *bgImg; /* background image to draw on */
  2334.     PhotoInstance *iPtr; /* image instance to draw */
  2335.     int xOffset, yOffset; /* X & Y offset into image instance to draw */
  2336.     int width, height; /* width & height of image to draw */
  2337. {
  2338.     int x, y, line;
  2339.     unsigned long pixel;
  2340.     unsigned char r, g, b, alpha, unalpha;
  2341.     unsigned char *alphaAr = iPtr->masterPtr->pix32;
  2342.     unsigned char *masterPtr;
  2343.     /*
  2344.      * This blending is an integer version of the Source-Over
  2345.      * compositing rule (see Porter&Duff, "Compositing Digital
  2346.      * Images", proceedings of SIGGRAPH 1984) that has been hard-coded
  2347.      * (for speed) to work with targetting a solid surface.
  2348.      */
  2349. #define ALPHA_BLEND(bgPix, imgPix, alpha, unalpha) 
  2350. ((bgPix * unalpha + imgPix * alpha) / 255)
  2351.     /*
  2352.      * We have to get the mask and shift info from the visual on
  2353.      * non-Win32 so that the macros Get*Value(), RGB() and RGB15()
  2354.      * work correctly.  This might be cached for better performance.
  2355.      */
  2356. #ifndef __WIN32__
  2357.     unsigned long red_mask, green_mask, blue_mask;
  2358.     unsigned long red_shift, green_shift, blue_shift;
  2359.     Visual *visual = iPtr->visualInfo.visual;
  2360.     red_mask = visual->red_mask;
  2361.     green_mask = visual->green_mask;
  2362.     blue_mask = visual->blue_mask;
  2363.     red_shift = 0;
  2364.     green_shift = 0;
  2365.     blue_shift = 0;
  2366.     while ((0x0001 & (red_mask >> red_shift)) == 0) {
  2367. red_shift++;
  2368.     }
  2369.     while ((0x0001 & (green_mask >> green_shift)) == 0) {
  2370. green_shift++;
  2371.     }
  2372.     while ((0x0001 & (blue_mask >> blue_shift)) == 0) {
  2373. blue_shift++;
  2374.     }
  2375. #endif /* !__WIN32__ */
  2376.     /*
  2377.      * Only unix requires the special case for <24bpp.  It varies with
  2378.      * 3 extra shifts and uses RGB15.  The 24+bpp version could also
  2379.      * then be further optimized.
  2380.      */
  2381. #if !(defined(__WIN32__) || defined(MAC_OSX_TK))
  2382.     if (bgImg->depth < 24) {
  2383. unsigned char red_mlen, green_mlen, blue_mlen;
  2384. red_mlen = 8 - CountBits(red_mask >> red_shift);
  2385. green_mlen = 8 - CountBits(green_mask >> green_shift);
  2386. blue_mlen = 8 - CountBits(blue_mask >> blue_shift);
  2387. for (y = 0; y < height; y++) {
  2388.     line = (y + yOffset) * iPtr->masterPtr->width;
  2389.     for (x = 0; x < width; x++) {
  2390. masterPtr = alphaAr + ((line + x + xOffset) * 4);
  2391. alpha = masterPtr[3];
  2392. /*
  2393.  * Ignore pixels that are fully transparent
  2394.  */
  2395. if (alpha) {
  2396.     /*
  2397.      * We could perhaps be more efficient than XGetPixel for
  2398.      * 24 and 32 bit displays, but this seems "fast enough".
  2399.      */
  2400.     r = masterPtr[0];
  2401.     g = masterPtr[1];
  2402.     b = masterPtr[2];
  2403.     if (alpha != 255) {
  2404. /*
  2405.  * Only blend pixels that have some transparency
  2406.  */
  2407. unsigned char ra, ga, ba;
  2408. pixel = XGetPixel(bgImg, x, y);
  2409. ra = GetRValue(pixel) << red_mlen;
  2410. ga = GetGValue(pixel) << green_mlen;
  2411. ba = GetBValue(pixel) << blue_mlen;
  2412. unalpha = 255 - alpha;
  2413. r = ALPHA_BLEND(ra, r, alpha, unalpha);
  2414. g = ALPHA_BLEND(ga, g, alpha, unalpha);
  2415. b = ALPHA_BLEND(ba, b, alpha, unalpha);
  2416.     }
  2417.     XPutPixel(bgImg, x, y, RGB15(r, g, b));
  2418. }
  2419.     }
  2420. }
  2421. return;
  2422.     }
  2423. #endif /* !__WIN32__ && !MAC_OSX_TK */
  2424.     for (y = 0; y < height; y++) {
  2425. line = (y + yOffset) * iPtr->masterPtr->width;
  2426. for (x = 0; x < width; x++) {
  2427.     masterPtr = alphaAr + ((line + x + xOffset) * 4);
  2428.     alpha = masterPtr[3];
  2429.     /*
  2430.      * Ignore pixels that are fully transparent
  2431.      */
  2432.     if (alpha) {
  2433. /*
  2434.  * We could perhaps be more efficient than XGetPixel for
  2435.  * 24 and 32 bit displays, but this seems "fast enough".
  2436.  */
  2437. r = masterPtr[0];
  2438. g = masterPtr[1];
  2439. b = masterPtr[2];
  2440. if (alpha != 255) {
  2441.     /*
  2442.      * Only blend pixels that have some transparency
  2443.      */
  2444.     unsigned char ra, ga, ba;
  2445.     pixel = XGetPixel(bgImg, x, y);
  2446.     ra = GetRValue(pixel);
  2447.     ga = GetGValue(pixel);
  2448.     ba = GetBValue(pixel);
  2449.     unalpha = 255 - alpha;
  2450.     r = ALPHA_BLEND(ra, r, alpha, unalpha);
  2451.     g = ALPHA_BLEND(ga, g, alpha, unalpha);
  2452.     b = ALPHA_BLEND(ba, b, alpha, unalpha);
  2453. }
  2454. XPutPixel(bgImg, x, y, RGB(r, g, b));
  2455.     }
  2456. }
  2457.     }
  2458. #undef ALPHA_BLEND
  2459. }
  2460. /*
  2461.  *----------------------------------------------------------------------
  2462.  *
  2463.  * ImgPhotoDisplay --
  2464.  *
  2465.  * This procedure is invoked to draw a photo image.
  2466.  *
  2467.  * Results:
  2468.  * None.
  2469.  *
  2470.  * Side effects:
  2471.  * A portion of the image gets rendered in a pixmap or window.
  2472.  *
  2473.  *----------------------------------------------------------------------
  2474.  */
  2475. static void
  2476. ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width,
  2477. height, drawableX, drawableY)
  2478.     ClientData clientData; /* Pointer to PhotoInstance structure for
  2479.  * for instance to be displayed. */
  2480.     Display *display; /* Display on which to draw image. */
  2481.     Drawable drawable; /* Pixmap or window in which to draw image. */
  2482.     int imageX, imageY; /* Upper-left corner of region within image
  2483.  * to draw. */
  2484.     int width, height; /* Dimensions of region within image to draw. */
  2485.     int drawableX, drawableY; /* Coordinates within drawable that
  2486.  * correspond to imageX and imageY. */
  2487. {
  2488.     PhotoInstance *instancePtr = (PhotoInstance *) clientData;
  2489.     XVisualInfo visInfo = instancePtr->visualInfo;
  2490.     /*
  2491.      * If there's no pixmap, it means that an error occurred
  2492.      * while creating the image instance so it can't be displayed.
  2493.      */
  2494.     if (instancePtr->pixels == None) {
  2495. return;
  2496.     }
  2497.     /*
  2498.      * Check for bogus widths/heights.  This prevents us from calling
  2499.      * XGetImage with a zero size, which it does not like. [Bug 979239]
  2500.      */
  2501.     if (width < 1 || height < 1) {
  2502. return;
  2503.     }
  2504.     if (
  2505. #if defined(MAC_TCL)
  2506. /*
  2507.  * The retrieval of bgImg is currently not functional on OS9
  2508.  * so skip attempts to alpha blend.
  2509.  */
  2510. 0 &&
  2511. #endif
  2512. (instancePtr->masterPtr->flags & COMPLEX_ALPHA)
  2513.     && visInfo.depth >= 15
  2514.     && (visInfo.class == DirectColor || visInfo.class == TrueColor)) {
  2515. Tk_ErrorHandler handler;
  2516. XImage *bgImg = NULL;
  2517. /*
  2518.  * Create an error handler to suppress the case where the input was
  2519.  * not properly constrained, which can cause an X error. [Bug 979239]
  2520.  */
  2521. handler = Tk_CreateErrorHandler(display, -1, -1, -1,
  2522. (Tk_ErrorProc *) NULL, (ClientData) NULL);
  2523. /*
  2524.  * Pull the current background from the display to blend with
  2525.  */
  2526. bgImg = XGetImage(display, drawable, drawableX, drawableY,
  2527. (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
  2528. if (bgImg == NULL) {
  2529.     Tk_DeleteErrorHandler(handler);
  2530.     return;
  2531. }
  2532. ImgPhotoBlendComplexAlpha(bgImg, instancePtr,
  2533. imageX, imageY, width, height);
  2534. /*
  2535.  * Color info is unimportant as we only do this operation for
  2536.  * depth >= 15.
  2537.  */
  2538. TkPutImage(NULL, 0, display, drawable, instancePtr->gc,
  2539. bgImg, 0, 0, drawableX, drawableY,
  2540. (unsigned int) width, (unsigned int) height);
  2541. XDestroyImage(bgImg);
  2542. Tk_DeleteErrorHandler(handler);
  2543.     } else {
  2544. /*
  2545.  * masterPtr->region describes which parts of the image contain
  2546.  * valid data.  We set this region as the clip mask for the gc,
  2547.  * setting its origin appropriately, and use it when drawing the
  2548.  * image.
  2549.  */
  2550. TkSetRegion(display, instancePtr->gc, instancePtr->masterPtr->validRegion);
  2551. XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
  2552.                drawableY - imageY);
  2553. XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc,
  2554.           imageX, imageY, (unsigned) width, (unsigned) height,
  2555.           drawableX, drawableY);
  2556. XSetClipMask(display, instancePtr->gc, None);
  2557. XSetClipOrigin(display, instancePtr->gc, 0, 0);
  2558.     }
  2559.     XFlush (display);
  2560. }
  2561. /*
  2562.  *----------------------------------------------------------------------
  2563.  *
  2564.  * ImgPhotoFree --
  2565.  *
  2566.  * This procedure is called when a widget ceases to use a
  2567.  * particular instance of an image.  We don't actually get
  2568.  * rid of the instance until later because we may be about
  2569.  * to get this instance again.
  2570.  *
  2571.  * Results:
  2572.  * None.
  2573.  *
  2574.  * Side effects:
  2575.  * Internal data structures get cleaned up, later.
  2576.  *
  2577.  *----------------------------------------------------------------------
  2578.  */
  2579. static void
  2580. ImgPhotoFree(clientData, display)
  2581.     ClientData clientData; /* Pointer to PhotoInstance structure for
  2582.  * for instance to be displayed. */
  2583.     Display *display; /* Display containing window that used image. */
  2584. {
  2585.     PhotoInstance *instancePtr = (PhotoInstance *) clientData;
  2586.     ColorTable *colorPtr;
  2587.     instancePtr->refCount -= 1;
  2588.     if (instancePtr->refCount > 0) {
  2589. return;
  2590.     }
  2591.     /*
  2592.      * There are no more uses of the image within this widget.
  2593.      * Decrement the count of live uses of its color table, so
  2594.      * that its colors can be reclaimed if necessary, and
  2595.      * set up an idle call to free the instance structure.
  2596.      */
  2597.     colorPtr = instancePtr->colorTablePtr;
  2598.     if (colorPtr != NULL) {
  2599. colorPtr->liveRefCount -= 1;
  2600.     }
  2601.     
  2602.     Tcl_DoWhenIdle(DisposeInstance, (ClientData) instancePtr);
  2603. }
  2604. /*
  2605.  *----------------------------------------------------------------------
  2606.  *
  2607.  * ImgPhotoDelete --
  2608.  *
  2609.  * This procedure is called by the image code to delete the
  2610.  * master structure for an image.
  2611.  *
  2612.  * Results:
  2613.  * None.
  2614.  *
  2615.  * Side effects:
  2616.  * Resources associated with the image get freed.
  2617.  *
  2618.  *----------------------------------------------------------------------
  2619.  */
  2620. static void
  2621. ImgPhotoDelete(masterData)
  2622.     ClientData masterData; /* Pointer to PhotoMaster structure for
  2623.  * image.  Must not have any more instances. */
  2624. {
  2625.     PhotoMaster *masterPtr = (PhotoMaster *) masterData;
  2626.     PhotoInstance *instancePtr;
  2627.     while ((instancePtr = masterPtr->instancePtr) != NULL) {
  2628. if (instancePtr->refCount > 0) {
  2629.     panic("tried to delete photo image when instances still exist");
  2630. }
  2631. Tcl_CancelIdleCall(DisposeInstance, (ClientData) instancePtr);
  2632. DisposeInstance((ClientData) instancePtr);
  2633.     }
  2634.     masterPtr->tkMaster = NULL;
  2635.     if (masterPtr->imageCmd != NULL) {
  2636. Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);
  2637.     }
  2638.     if (masterPtr->pix32 != NULL) {
  2639. ckfree((char *) masterPtr->pix32);
  2640.     }
  2641.     if (masterPtr->validRegion != NULL) {
  2642. TkDestroyRegion(masterPtr->validRegion);
  2643.     }
  2644.     if (masterPtr->dataString != NULL) {
  2645. Tcl_DecrRefCount(masterPtr->dataString);
  2646.     }
  2647.     if (masterPtr->format != NULL) {
  2648. Tcl_DecrRefCount(masterPtr->format);
  2649.     }
  2650.     Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0);
  2651.     ckfree((char *) masterPtr);
  2652. }
  2653. /*
  2654.  *----------------------------------------------------------------------
  2655.  *
  2656.  * ImgPhotoCmdDeletedProc --
  2657.  *
  2658.  * This procedure is invoked when the image command for an image
  2659.  * is deleted.  It deletes the image.
  2660.  *
  2661.  * Results:
  2662.  * None.
  2663.  *
  2664.  * Side effects:
  2665.  * The image is deleted.
  2666.  *
  2667.  *----------------------------------------------------------------------
  2668.  */
  2669. static void
  2670. ImgPhotoCmdDeletedProc(clientData)
  2671.     ClientData clientData; /* Pointer to PhotoMaster structure for
  2672.  * image. */
  2673. {
  2674.     PhotoMaster *masterPtr = (PhotoMaster *) clientData;
  2675.     masterPtr->imageCmd = NULL;
  2676.     if (masterPtr->tkMaster != NULL) {
  2677. Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
  2678.     }
  2679. }
  2680. /*
  2681.  *----------------------------------------------------------------------
  2682.  *
  2683.  * ImgPhotoSetSize --
  2684.  *
  2685.  * This procedure reallocates the image storage and instance
  2686.  * pixmaps for a photo image, as necessary, to change the
  2687.  * image's size to `width' x `height' pixels.
  2688.  *
  2689.  * Results:
  2690.  * TCL_OK if successful, TCL_ERROR if failure occurred (currently
  2691.  * just with memory allocation.)
  2692.  *
  2693.  * Side effects:
  2694.  * Storage gets reallocated, for the master and all its instances.
  2695.  *
  2696.  *----------------------------------------------------------------------
  2697.  */
  2698. static int
  2699. ImgPhotoSetSize(masterPtr, width, height)
  2700.     PhotoMaster *masterPtr;
  2701.     int width, height;
  2702. {
  2703.     unsigned char *newPix32 = NULL;
  2704.     int h, offset, pitch;
  2705.     unsigned char *srcPtr, *destPtr;
  2706.     XRectangle validBox, clipBox;
  2707.     TkRegion clipRegion;
  2708.     PhotoInstance *instancePtr;
  2709.     if (masterPtr->userWidth > 0) {
  2710. width = masterPtr->userWidth;
  2711.     }
  2712.     if (masterPtr->userHeight > 0) {
  2713. height = masterPtr->userHeight;
  2714.     }
  2715.     pitch = width * 4;
  2716.     /*
  2717.      * Test if we're going to (re)allocate the main buffer now, so
  2718.      * that any failures will leave the photo unchanged.
  2719.      */
  2720.     if ((width != masterPtr->width) || (height != masterPtr->height)
  2721.     || (masterPtr->pix32 == NULL)) {
  2722. /*
  2723.  * Not a u-long, but should be one.
  2724.  */
  2725. unsigned /*long*/ newPixSize = (unsigned /*long*/) (height * pitch);
  2726. /*
  2727.  * Some mallocs() really hate allocating zero bytes. [Bug 619544]
  2728.  */
  2729. if (newPixSize == 0) {
  2730.     newPix32 = NULL;
  2731. } else {
  2732.     newPix32 = (unsigned char *) attemptckalloc(newPixSize);
  2733.     if (newPix32 == NULL) {
  2734. return TCL_ERROR;
  2735.     }
  2736. }
  2737.     }
  2738.     /*
  2739.      * We have to trim the valid region if it is currently
  2740.      * larger than the new image size.
  2741.      */
  2742.     TkClipBox(masterPtr->validRegion, &validBox);
  2743.     if ((validBox.x + validBox.width > width)
  2744.     || (validBox.y + validBox.height > height)) {
  2745. clipBox.x = 0;
  2746. clipBox.y = 0;
  2747. clipBox.width = width;
  2748. clipBox.height = height;
  2749. clipRegion = TkCreateRegion();
  2750. TkUnionRectWithRegion(&clipBox, clipRegion, clipRegion);