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
23#include "tkInt.h"
24#include "tkPort.h"
25#include "tclMath.h"
26#include <ctype.h>
27
28#ifdef __WIN32__
29#include "tkWinInt.h"
30#endif
31
32/*
33 * Declaration for internal Xlib function used here:
34 */
35
36extern int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image));
37
38/*
39 * A signed 8-bit integral type.  If chars are unsigned and the compiler
40 * isn't an ANSI one, then we have to use short instead (which wastes
41 * space) to get signed behavior.
42 */
43
44#if defined(__STDC__) || defined(_AIX)
45    typedef signed char schar;
46#else
47#   ifndef __CHAR_UNSIGNED__
48	typedef char schar;
49#   else
50	typedef short schar;
51#   endif
52#endif
53
54/*
55 * An unsigned 32-bit integral type, used for pixel values.
56 * We use int rather than long here to accommodate those systems
57 * where longs are 64 bits.
58 */
59
60typedef unsigned int pixel;
61
62/*
63 * The maximum number of pixels to transmit to the server in a
64 * single XPutImage call.
65 */
66
67#define MAX_PIXELS 65536
68
69/*
70 * The set of colors required to display a photo image in a window depends on:
71 *	- the visual used by the window
72 *	- the palette, which specifies how many levels of each primary
73 *	  color to use, and
74 *	- the gamma value for the image.
75 *
76 * Pixel values allocated for specific colors are valid only for the
77 * colormap in which they were allocated.  Sets of pixel values
78 * allocated for displaying photos are re-used in other windows if
79 * possible, that is, if the display, colormap, palette and gamma
80 * values match.  A hash table is used to locate these sets of pixel
81 * values, using the following data structure as key:
82 */
83
84typedef struct {
85    Display *display;		/* Qualifies the colormap resource ID */
86    Colormap colormap;		/* Colormap that the windows are using. */
87    double gamma;		/* Gamma exponent value for images. */
88    Tk_Uid palette;		/* Specifies how many shades of each primary
89				 * we want to allocate. */
90} ColorTableId;
91
92/*
93 * For a particular (display, colormap, palette, gamma) combination,
94 * a data structure of the following type is used to store the allocated
95 * pixel values and other information:
96 */
97
98typedef struct ColorTable {
99    ColorTableId id;		/* Information used in selecting this
100				 * color table. */
101    int	flags;			/* See below. */
102    int	refCount;		/* Number of instances using this map. */
103    int liveRefCount;		/* Number of instances which are actually
104				 * in use, using this map. */
105    int	numColors;		/* Number of colors allocated for this map. */
106
107    XVisualInfo	visualInfo;	/* Information about the visual for windows
108				 * using this color table. */
109
110    pixel redValues[256];	/* Maps 8-bit values of red intensity
111				 * to a pixel value or index in pixelMap. */
112    pixel greenValues[256];	/* Ditto for green intensity */
113    pixel blueValues[256];	/* Ditto for blue intensity */
114    unsigned long *pixelMap;	/* Actual pixel values allocated. */
115
116    unsigned char colorQuant[3][256];
117				/* Maps 8-bit intensities to quantized
118				 * intensities.  The first index is 0 for
119				 * red, 1 for green, 2 for blue. */
120} ColorTable;
121
122/*
123 * Bit definitions for the flags field of a ColorTable.
124 * BLACK_AND_WHITE:		1 means only black and white colors are
125 *				available.
126 * COLOR_WINDOW:		1 means a full 3-D color cube has been
127 *				allocated.
128 * DISPOSE_PENDING:		1 means a call to DisposeColorTable has
129 *				been scheduled as an idle handler, but it
130 *				hasn't been invoked yet.
131 * MAP_COLORS:			1 means pixel values should be mapped
132 *				through pixelMap.
133 */
134#ifdef COLOR_WINDOW
135#undef COLOR_WINDOW
136#endif
137
138#define BLACK_AND_WHITE		1
139#define COLOR_WINDOW		2
140#define DISPOSE_PENDING		4
141#define MAP_COLORS		8
142
143/*
144 * Definition of the data associated with each photo image master.
145 */
146
147typedef struct PhotoMaster {
148    Tk_ImageMaster tkMaster;	/* Tk's token for image master.  NULL means
149				 * the image is being deleted. */
150    Tcl_Interp *interp;		/* Interpreter associated with the
151				 * application using this image. */
152    Tcl_Command imageCmd;	/* Token for image command (used to delete
153				 * it when the image goes away).  NULL means
154				 * the image command has already been
155				 * deleted. */
156    int	flags;			/* Sundry flags, defined below. */
157    int	width, height;		/* Dimensions of image. */
158    int userWidth, userHeight;	/* User-declared image dimensions. */
159    Tk_Uid palette;		/* User-specified default palette for
160				 * instances of this image. */
161    double gamma;		/* Display gamma value to correct for. */
162    char *fileString;		/* Name of file to read into image. */
163    Tcl_Obj *dataString;	/* Object to use as contents of image. */
164    Tcl_Obj *format;		/* User-specified format of data in image
165				 * file or string value. */
166    unsigned char *pix32;	/* Local storage for 32-bit image. */
167    int ditherX, ditherY;	/* Location of first incorrectly
168				 * dithered pixel in image. */
169    TkRegion validRegion;	/* Tk region indicating which parts of
170				 * the image have valid image data. */
171    struct PhotoInstance *instancePtr;
172				/* First in the list of instances
173				 * associated with this master. */
174} PhotoMaster;
175
176/*
177 * Bit definitions for the flags field of a PhotoMaster.
178 * COLOR_IMAGE:			1 means that the image has different color
179 *				components.
180 * IMAGE_CHANGED:		1 means that the instances of this image
181 *				need to be redithered.
182 * COMPLEX_ALPHA:		1 means that the instances of this image
183 *				have alpha values that aren't 0 or 255.
184 */
185
186#define COLOR_IMAGE		1
187#define IMAGE_CHANGED		2
188#define COMPLEX_ALPHA		4
189
190/*
191 * Flag to OR with the compositing rule to indicate that the source, despite
192 * having an alpha channel, has simple alpha.
193 */
194
195#define SOURCE_IS_SIMPLE_ALPHA_PHOTO 0x10000000
196
197/*
198 * The following data structure represents all of the instances of
199 * a photo image in windows on a given screen that are using the
200 * same colormap.
201 */
202
203typedef struct PhotoInstance {
204    PhotoMaster *masterPtr;	/* Pointer to master for image. */
205    Display *display;		/* Display for windows using this instance. */
206    Colormap colormap;		/* The image may only be used in windows with
207				 * this particular colormap. */
208    struct PhotoInstance *nextPtr;
209				/* Pointer to the next instance in the list
210				 * of instances associated with this master. */
211    int refCount;		/* Number of instances using this structure. */
212    Tk_Uid palette;		/* Palette for these particular instances. */
213    double gamma;		/* Gamma value for these instances. */
214    Tk_Uid defaultPalette;	/* Default palette to use if a palette
215				 * is not specified for the master. */
216    ColorTable *colorTablePtr;	/* Pointer to information about colors
217				 * allocated for image display in windows
218				 * like this one. */
219    Pixmap pixels;		/* X pixmap containing dithered image. */
220    int width, height;		/* Dimensions of the pixmap. */
221    schar *error;		/* Error image, used in dithering. */
222    XImage *imagePtr;		/* Image structure for converted pixels. */
223    XVisualInfo visualInfo;	/* Information about the visual that these
224				 * windows are using. */
225    GC gc;			/* Graphics context for writing images
226				 * to the pixmap. */
227} PhotoInstance;
228
229/*
230 * The following data structure is used to return information
231 * from ParseSubcommandOptions:
232 */
233
234struct SubcommandOptions {
235    int options;		/* Individual bits indicate which
236				 * options were specified - see below. */
237    Tcl_Obj *name;		/* Name specified without an option. */
238    int fromX, fromY;		/* Values specified for -from option. */
239    int fromX2, fromY2;		/* Second coordinate pair for -from option. */
240    int toX, toY;		/* Values specified for -to option. */
241    int toX2, toY2;		/* Second coordinate pair for -to option. */
242    int zoomX, zoomY;		/* Values specified for -zoom option. */
243    int subsampleX, subsampleY;	/* Values specified for -subsample option. */
244    Tcl_Obj *format;		/* Value specified for -format option. */
245    XColor *background;		/* Value specified for -background option. */
246    int compositingRule;	/* Value specified for -compositingrule opt */
247};
248
249/*
250 * Bit definitions for use with ParseSubcommandOptions:
251 * Each bit is set in the allowedOptions parameter on a call to
252 * ParseSubcommandOptions if that option is allowed for the current
253 * photo image subcommand.  On return, the bit is set in the options
254 * field of the SubcommandOptions structure if that option was specified.
255 *
256 * OPT_BACKGROUND:		Set if -format option allowed/specified.
257 * OPT_COMPOSITE:		Set if -compositingrule option allowed/spec'd.
258 * OPT_FORMAT:			Set if -format option allowed/specified.
259 * OPT_FROM:			Set if -from option allowed/specified.
260 * OPT_GRAYSCALE:		Set if -grayscale option allowed/specified.
261 * OPT_SHRINK:			Set if -shrink option allowed/specified.
262 * OPT_SUBSAMPLE:		Set if -subsample option allowed/spec'd.
263 * OPT_TO:			Set if -to option allowed/specified.
264 * OPT_ZOOM:			Set if -zoom option allowed/specified.
265 */
266
267#define OPT_BACKGROUND	1
268#define OPT_COMPOSITE	2
269#define OPT_FORMAT	4
270#define OPT_FROM	8
271#define OPT_GRAYSCALE	0x10
272#define OPT_SHRINK	0x20
273#define OPT_SUBSAMPLE	0x40
274#define OPT_TO		0x80
275#define OPT_ZOOM	0x100
276
277/*
278 * List of option names.  The order here must match the order of
279 * declarations of the OPT_* constants above.
280 */
281
282static char *optionNames[] = {
283    "-background",
284    "-compositingrule",
285    "-format",
286    "-from",
287    "-grayscale",
288    "-shrink",
289    "-subsample",
290    "-to",
291    "-zoom",
292    (char *) NULL
293};
294
295/*
296 * Message to generate when an attempt to resize an image fails due
297 * to memory problems.
298 */
299#define TK_PHOTO_ALLOC_FAILURE_MESSAGE \
300	"not enough free memory for image buffer"
301
302/*
303 * Functions used in the type record for photo images.
304 */
305
306static int		ImgPhotoCreate _ANSI_ARGS_((Tcl_Interp *interp,
307			    char *name, int objc, Tcl_Obj *CONST objv[],
308			    Tk_ImageType *typePtr, Tk_ImageMaster master,
309			    ClientData *clientDataPtr));
310static ClientData	ImgPhotoGet _ANSI_ARGS_((Tk_Window tkwin,
311			    ClientData clientData));
312static void		ImgPhotoDisplay _ANSI_ARGS_((ClientData clientData,
313			    Display *display, Drawable drawable,
314			    int imageX, int imageY, int width, int height,
315			    int drawableX, int drawableY));
316static void		ImgPhotoFree _ANSI_ARGS_((ClientData clientData,
317			    Display *display));
318static void		ImgPhotoDelete _ANSI_ARGS_((ClientData clientData));
319static int		ImgPhotoPostscript _ANSI_ARGS_((ClientData clientData,
320			    Tcl_Interp *interp, Tk_Window tkwin,
321			    Tk_PostscriptInfo psInfo, int x, int y, int width,
322			    int height, int prepass));
323
324/*
325 * The type record itself for photo images:
326 */
327
328Tk_ImageType tkPhotoImageType = {
329    "photo",			/* name */
330    ImgPhotoCreate,		/* createProc */
331    ImgPhotoGet,		/* getProc */
332    ImgPhotoDisplay,		/* displayProc */
333    ImgPhotoFree,		/* freeProc */
334    ImgPhotoDelete,		/* deleteProc */
335    ImgPhotoPostscript,		/* postscriptProc */
336    (Tk_ImageType *) NULL	/* nextPtr */
337};
338
339typedef struct ThreadSpecificData {
340    Tk_PhotoImageFormat *formatList;  /* Pointer to the first in the
341				       * list of known photo image formats.*/
342    Tk_PhotoImageFormat *oldFormatList;  /* Pointer to the first in the
343				       * list of known photo image formats.*/
344    int initialized;	/* set to 1 if we've initialized the strucuture */
345} ThreadSpecificData;
346static Tcl_ThreadDataKey dataKey;
347
348/*
349 * Default configuration
350 */
351
352#define DEF_PHOTO_GAMMA		"1"
353#define DEF_PHOTO_HEIGHT	"0"
354#define DEF_PHOTO_PALETTE	""
355#define DEF_PHOTO_WIDTH		"0"
356
357/*
358 * Information used for parsing configuration specifications:
359 */
360static Tk_ConfigSpec configSpecs[] = {
361    {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
362	 (char *) NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK},
363    {TK_CONFIG_DOUBLE, "-gamma", (char *) NULL, (char *) NULL,
364	 DEF_PHOTO_GAMMA, Tk_Offset(PhotoMaster, gamma), 0},
365    {TK_CONFIG_INT, "-height", (char *) NULL, (char *) NULL,
366	 DEF_PHOTO_HEIGHT, Tk_Offset(PhotoMaster, userHeight), 0},
367    {TK_CONFIG_UID, "-palette", (char *) NULL, (char *) NULL,
368	 DEF_PHOTO_PALETTE, Tk_Offset(PhotoMaster, palette), 0},
369    {TK_CONFIG_INT, "-width", (char *) NULL, (char *) NULL,
370	 DEF_PHOTO_WIDTH, Tk_Offset(PhotoMaster, userWidth), 0},
371    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
372	 (char *) NULL, 0, 0}
373};
374
375/*
376 * Hash table used to hash from (display, colormap, palette, gamma)
377 * to ColorTable address.
378 */
379
380static Tcl_HashTable imgPhotoColorHash;
381static int imgPhotoColorHashInitialized;
382#define N_COLOR_HASH	(sizeof(ColorTableId) / sizeof(int))
383
384/*
385 * Implementation of the Porter-Duff Source-Over compositing rule.
386 */
387
388#define PD_SRC_OVER(srcColor,srcAlpha,dstColor,dstAlpha) \
389	(srcColor*srcAlpha/255) + dstAlpha*(255-srcAlpha)/255*dstColor/255
390#define PD_SRC_OVER_ALPHA(srcAlpha,dstAlpha) \
391	(srcAlpha + (255-srcAlpha)*dstAlpha/255)
392
393/*
394 * Forward declarations
395 */
396
397static void		PhotoFormatThreadExitProc _ANSI_ARGS_((
398			    ClientData clientData));
399static int		ImgPhotoCmd _ANSI_ARGS_((ClientData clientData,
400			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
401static int		ParseSubcommandOptions _ANSI_ARGS_((
402			    struct SubcommandOptions *optPtr,
403			    Tcl_Interp *interp, int allowedOptions,
404			    int *indexPtr, int objc, Tcl_Obj *CONST objv[]));
405static void		ImgPhotoCmdDeletedProc _ANSI_ARGS_((
406			    ClientData clientData));
407static int		ImgPhotoConfigureMaster _ANSI_ARGS_((
408			    Tcl_Interp *interp, PhotoMaster *masterPtr,
409			    int objc, Tcl_Obj *CONST objv[], int flags));
410static void		ImgPhotoConfigureInstance _ANSI_ARGS_((
411			    PhotoInstance *instancePtr));
412static int              ToggleComplexAlphaIfNeeded _ANSI_ARGS_((
413                            PhotoMaster *mPtr));
414static void             ImgPhotoBlendComplexAlpha _ANSI_ARGS_((
415			    XImage *bgImg, PhotoInstance *iPtr,
416			    int xOffset, int yOffset, int width, int height));
417static int		ImgPhotoSetSize _ANSI_ARGS_((PhotoMaster *masterPtr,
418			    int width, int height));
419static void		ImgPhotoInstanceSetSize _ANSI_ARGS_((
420			    PhotoInstance *instancePtr));
421static int		ImgStringWrite _ANSI_ARGS_((Tcl_Interp *interp,
422			    Tcl_Obj *formatString,
423			    Tk_PhotoImageBlock *blockPtr));
424static char *		ImgGetPhoto _ANSI_ARGS_((PhotoMaster *masterPtr,
425			    Tk_PhotoImageBlock *blockPtr,
426			    struct SubcommandOptions *optPtr));
427static int		IsValidPalette _ANSI_ARGS_((PhotoInstance *instancePtr,
428			    CONST char *palette));
429static int		CountBits _ANSI_ARGS_((pixel mask));
430static void		GetColorTable _ANSI_ARGS_((PhotoInstance *instancePtr));
431static void		FreeColorTable _ANSI_ARGS_((ColorTable *colorPtr,
432			    int force));
433static void		AllocateColors _ANSI_ARGS_((ColorTable *colorPtr));
434static void		DisposeColorTable _ANSI_ARGS_((ClientData clientData));
435static void		DisposeInstance _ANSI_ARGS_((ClientData clientData));
436static int		ReclaimColors _ANSI_ARGS_((ColorTableId *id,
437			    int numColors));
438static int		MatchFileFormat _ANSI_ARGS_((Tcl_Interp *interp,
439			    Tcl_Channel chan, char *fileName, Tcl_Obj *formatString,
440			    Tk_PhotoImageFormat **imageFormatPtr,
441			    int *widthPtr, int *heightPtr, int *oldformat));
442static int		MatchStringFormat _ANSI_ARGS_((Tcl_Interp *interp,
443			    Tcl_Obj *data, Tcl_Obj *formatString,
444			    Tk_PhotoImageFormat **imageFormatPtr,
445			    int *widthPtr, int *heightPtr, int *oldformat));
446static Tcl_ObjCmdProc *	PhotoOptionFind _ANSI_ARGS_((Tcl_Interp * interp,
447			    Tcl_Obj *obj));
448static void		DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr,
449			    int x, int y, int width, int height));
450static void		PhotoOptionCleanupProc _ANSI_ARGS_((
451			    ClientData clientData, Tcl_Interp *interp));
452
453#undef MIN
454#define MIN(a, b)	((a) < (b)? (a): (b))
455#undef MAX
456#define MAX(a, b)	((a) > (b)? (a): (b))
457
458/*
459 *----------------------------------------------------------------------
460 *
461 * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat --
462 *
463 *	This procedure is invoked by an image file handler to register
464 *	a new photo image format and the procedures that handle the
465 *	new format.  The procedure is typically invoked during
466 *	Tcl_AppInit.
467 *
468 * Results:
469 *	None.
470 *
471 * Side effects:
472 *	The new image file format is entered into a table used in the
473 *	photo image "read" and "write" subcommands.
474 *
475 *----------------------------------------------------------------------
476 */
477
478static void
479PhotoFormatThreadExitProc(clientData)
480    ClientData clientData;	/* not used */
481{
482    Tk_PhotoImageFormat *freePtr;
483    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
484            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
485
486    while (tsdPtr->oldFormatList != NULL) {
487	freePtr = tsdPtr->oldFormatList;
488	tsdPtr->oldFormatList = tsdPtr->oldFormatList->nextPtr;
489	ckfree((char *) freePtr->name);
490	ckfree((char *) freePtr);
491    }
492    while (tsdPtr->formatList != NULL) {
493	freePtr = tsdPtr->formatList;
494	tsdPtr->formatList = tsdPtr->formatList->nextPtr;
495	ckfree((char *) freePtr->name);
496	ckfree((char *) freePtr);
497    }
498}
499
500/*
501 *----------------------------------------------------------------------
502 *
503 * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat --
504 *
505 *	This procedure is invoked by an image file handler to register
506 *	a new photo image format and the procedures that handle the
507 *	new format.  The procedure is typically invoked during
508 *	Tcl_AppInit.
509 *
510 * Results:
511 *	None.
512 *
513 * Side effects:
514 *	The new image file format is entered into a table used in the
515 *	photo image "read" and "write" subcommands.
516 *
517 *----------------------------------------------------------------------
518 */
519void
520Tk_CreateOldPhotoImageFormat(formatPtr)
521    Tk_PhotoImageFormat *formatPtr;
522				/* Structure describing the format.  All of
523				 * the fields except "nextPtr" must be filled
524				 * in by caller.  Must not have been passed
525				 * to Tk_CreatePhotoImageFormat previously. */
526{
527    Tk_PhotoImageFormat *copyPtr;
528    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
529            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
530
531    if (!tsdPtr->initialized) {
532	tsdPtr->initialized = 1;
533	Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);
534    }
535    copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat));
536    *copyPtr = *formatPtr;
537    copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1));
538    strcpy(copyPtr->name, formatPtr->name);
539    copyPtr->nextPtr = tsdPtr->oldFormatList;
540    tsdPtr->oldFormatList = copyPtr;
541}
542
543void
544Tk_CreatePhotoImageFormat(formatPtr)
545    Tk_PhotoImageFormat *formatPtr;
546				/* Structure describing the format.  All of
547				 * the fields except "nextPtr" must be filled
548				 * in by caller.  Must not have been passed
549				 * to Tk_CreatePhotoImageFormat previously. */
550{
551    Tk_PhotoImageFormat *copyPtr;
552    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
553            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
554
555    if (!tsdPtr->initialized) {
556	tsdPtr->initialized = 1;
557	Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);
558    }
559    copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat));
560    *copyPtr = *formatPtr;
561    copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1));
562    strcpy(copyPtr->name, formatPtr->name);
563    if (isupper((unsigned char) *formatPtr->name)) {
564	copyPtr->nextPtr = tsdPtr->oldFormatList;
565	tsdPtr->oldFormatList = copyPtr;
566    } else {
567	copyPtr->nextPtr = tsdPtr->formatList;
568	tsdPtr->formatList = copyPtr;
569    }
570}
571
572/*
573 *----------------------------------------------------------------------
574 *
575 * ImgPhotoCreate --
576 *
577 *	This procedure is called by the Tk image code to create
578 *	a new photo image.
579 *
580 * Results:
581 *	A standard Tcl result.
582 *
583 * Side effects:
584 *	The data structure for a new photo image is allocated and
585 *	initialized.
586 *
587 *----------------------------------------------------------------------
588 */
589
590static int
591ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr)
592    Tcl_Interp *interp;		/* Interpreter for application containing
593				 * image. */
594    char *name;			/* Name to use for image. */
595    int objc;			/* Number of arguments. */
596    Tcl_Obj *CONST objv[];	/* Argument objects for options (doesn't
597				 * include image name or type). */
598    Tk_ImageType *typePtr;	/* Pointer to our type record (not used). */
599    Tk_ImageMaster master;	/* Token for image, to be used by us in
600				 * later callbacks. */
601    ClientData *clientDataPtr;	/* Store manager's token for image here;
602				 * it will be returned in later callbacks. */
603{
604    PhotoMaster *masterPtr;
605
606    /*
607     * Allocate and initialize the photo image master record.
608     */
609
610    masterPtr = (PhotoMaster *) ckalloc(sizeof(PhotoMaster));
611    memset((void *) masterPtr, 0, sizeof(PhotoMaster));
612    masterPtr->tkMaster = master;
613    masterPtr->interp = interp;
614    masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd,
615	    (ClientData) masterPtr, ImgPhotoCmdDeletedProc);
616    masterPtr->palette = NULL;
617    masterPtr->pix32 = NULL;
618    masterPtr->instancePtr = NULL;
619    masterPtr->validRegion = TkCreateRegion();
620
621    /*
622     * Process configuration options given in the image create command.
623     */
624
625    if (ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, 0) != TCL_OK) {
626	ImgPhotoDelete((ClientData) masterPtr);
627	return TCL_ERROR;
628    }
629
630    *clientDataPtr = (ClientData) masterPtr;
631    return TCL_OK;
632}
633
634/*
635 *----------------------------------------------------------------------
636 *
637 * ImgPhotoCmd --
638 *
639 *	This procedure is invoked to process the Tcl command that
640 *	corresponds to a photo image.  See the user documentation
641 *	for details on what it does.
642 *
643 * Results:
644 *	A standard Tcl result.
645 *
646 * Side effects:
647 *	See the user documentation.
648 *
649 *----------------------------------------------------------------------
650 */
651
652static int
653ImgPhotoCmd(clientData, interp, objc, objv)
654    ClientData clientData;	/* Information about photo master. */
655    Tcl_Interp *interp;		/* Current interpreter. */
656    int objc;			/* Number of arguments. */
657    Tcl_Obj *CONST objv[];	/* Argument objects. */
658{
659    int oldformat = 0;
660    static CONST char *photoOptions[] = {
661	"blank", "cget", "configure", "copy", "data", "get", "put",
662	"read", "redither", "transparency", "write", (char *) NULL
663    };
664    enum options {
665	PHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA,
666	PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_TRANS,
667	PHOTO_WRITE
668    };
669
670    PhotoMaster *masterPtr = (PhotoMaster *) clientData;
671    int result, index;
672    int x, y, width, height;
673    int dataWidth, dataHeight;
674    struct SubcommandOptions options;
675    int listArgc;
676    CONST char **listArgv;
677    CONST char **srcArgv;
678    unsigned char *pixelPtr;
679    Tk_PhotoImageBlock block;
680    Tk_Window tkwin;
681    XColor color;
682    Tk_PhotoImageFormat *imageFormat;
683    int imageWidth, imageHeight;
684    int length, matched;
685    Tcl_Channel chan;
686    Tk_PhotoHandle srcHandle;
687    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
688            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
689
690    if (objc < 2) {
691	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
692	return TCL_ERROR;
693    }
694
695    if (Tcl_GetIndexFromObj(interp, objv[1], photoOptions, "option", 0,
696	    &index) != TCL_OK) {
697	Tcl_ObjCmdProc *proc;
698	proc = PhotoOptionFind(interp, objv[1]);
699	if (proc == (Tcl_ObjCmdProc *) NULL) {
700	    return TCL_ERROR;
701	}
702	return proc(clientData, interp, objc, objv);
703    }
704
705    switch ((enum options) index) {
706    case PHOTO_BLANK:
707	/*
708	 * photo blank command - just call Tk_PhotoBlank.
709	 */
710
711	if (objc == 2) {
712	    Tk_PhotoBlank(masterPtr);
713	    return TCL_OK;
714	} else {
715	    Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
716	    return TCL_ERROR;
717	}
718
719    case PHOTO_CGET: {
720	char *arg;
721
722	if (objc != 3) {
723	    Tcl_WrongNumArgs(interp, 2, objv, "option");
724	    return TCL_ERROR;
725	}
726	arg = Tcl_GetStringFromObj(objv[2], &length);
727	if (strncmp(arg,"-data", (unsigned) length) == 0) {
728	    if (masterPtr->dataString) {
729		Tcl_SetObjResult(interp, masterPtr->dataString);
730	    }
731	} else if (strncmp(arg,"-format", (unsigned) length) == 0) {
732	    if (masterPtr->format) {
733		Tcl_SetObjResult(interp, masterPtr->format);
734	    }
735	} else {
736	    Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
737		    (char *) masterPtr, Tcl_GetString(objv[2]), 0);
738	}
739	return TCL_OK;
740    }
741
742    case PHOTO_CONFIGURE:
743	/*
744	 * photo configure command - handle this in the standard way.
745	 */
746
747	if (objc == 2) {
748	    Tcl_Obj *obj, *subobj;
749	    result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
750		    configSpecs, (char *) masterPtr, (char *) NULL, 0);
751	    if (result != TCL_OK) {
752		return result;
753	    }
754	    obj = Tcl_NewObj();
755	    subobj = Tcl_NewStringObj("-data {} {} {}", 14);
756	    if (masterPtr->dataString) {
757		Tcl_ListObjAppendElement(interp, subobj, masterPtr->dataString);
758	    } else {
759		Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL);
760	    }
761	    Tcl_ListObjAppendElement(interp, obj, subobj);
762	    subobj = Tcl_NewStringObj("-format {} {} {}", 16);
763	    if (masterPtr->format) {
764		Tcl_ListObjAppendElement(interp, subobj, masterPtr->format);
765	    } else {
766		Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL);
767	    }
768	    Tcl_ListObjAppendElement(interp, obj, subobj);
769	    Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp));
770	    Tcl_SetObjResult(interp, obj);
771	    return TCL_OK;
772	}
773	if (objc == 3) {
774	    char *arg = Tcl_GetStringFromObj(objv[2], &length);
775
776	    if (!strncmp(arg, "-data", (unsigned) length)) {
777		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
778			"-data {} {} {}", (char *) NULL);
779		if (masterPtr->dataString) {
780		    Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
781			    masterPtr->dataString);
782		} else {
783		    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
784			    " {}", (char *) NULL);
785		}
786		return TCL_OK;
787	    } else if (!strncmp(arg, "-format", (unsigned) length)) {
788		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
789			"-format {} {} {}", (char *) NULL);
790		if (masterPtr->format) {
791		    Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
792			    masterPtr->format);
793		} else {
794		    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
795			    " {}", (char *) NULL);
796		}
797		return TCL_OK;
798	    } else {
799		return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
800			configSpecs, (char *) masterPtr, arg, 0);
801	    }
802	}
803	return ImgPhotoConfigureMaster(interp, masterPtr, objc-2, objv+2,
804		TK_CONFIG_ARGV_ONLY);
805
806    case PHOTO_COPY:
807	/*
808	 * photo copy command - first parse options.
809	 */
810
811	index = 2;
812	memset((VOID *) &options, 0, sizeof(options));
813	options.zoomX = options.zoomY = 1;
814	options.subsampleX = options.subsampleY = 1;
815	options.name = NULL;
816	options.compositingRule = TK_PHOTO_COMPOSITE_OVERLAY;
817	if (ParseSubcommandOptions(&options, interp,
818		OPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK |
819		OPT_COMPOSITE, &index, objc, objv) != TCL_OK) {
820	    return TCL_ERROR;
821	}
822	if (options.name == NULL || index < objc) {
823	    Tcl_WrongNumArgs(interp, 2, objv,
824		    "source-image ?-compositingrule rule? ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?");
825	    return TCL_ERROR;
826	}
827
828	/*
829	 * Look for the source image and get a pointer to its image data.
830	 * Check the values given for the -from option.
831	 */
832
833	srcHandle = Tk_FindPhoto(interp, Tcl_GetString(options.name));
834	if (srcHandle == NULL) {
835	    Tcl_AppendResult(interp, "image \"",
836		    Tcl_GetString(options.name), "\" doesn't",
837		    " exist or is not a photo image", (char *) NULL);
838	    return TCL_ERROR;
839	}
840	Tk_PhotoGetImage(srcHandle, &block);
841	if ((options.fromX2 > block.width) || (options.fromY2 > block.height)
842		|| (options.fromX2 > block.width)
843		|| (options.fromY2 > block.height)) {
844	    Tcl_AppendResult(interp, "coordinates for -from option extend ",
845		    "outside source image", (char *) NULL);
846	    return TCL_ERROR;
847	}
848
849	/*
850	 * Hack to pass through the message that the place we're coming from
851	 * has a simple alpha channel.
852	 */
853
854	if (!(((PhotoMaster *) srcHandle)->flags & COMPLEX_ALPHA)) {
855	    options.compositingRule |= SOURCE_IS_SIMPLE_ALPHA_PHOTO;
856	}
857
858	/*
859	 * Fill in default values for unspecified parameters.
860	 */
861
862	if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
863	    options.fromX2 = block.width;
864	    options.fromY2 = block.height;
865	}
866	if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
867	    width = options.fromX2 - options.fromX;
868	    if (options.subsampleX > 0) {
869		width = (width + options.subsampleX - 1) / options.subsampleX;
870	    } else if (options.subsampleX == 0) {
871		width = 0;
872	    } else {
873		width = (width - options.subsampleX - 1) / -options.subsampleX;
874	    }
875	    options.toX2 = options.toX + width * options.zoomX;
876
877	    height = options.fromY2 - options.fromY;
878	    if (options.subsampleY > 0) {
879		height = (height + options.subsampleY - 1)
880			/ options.subsampleY;
881	    } else if (options.subsampleY == 0) {
882		height = 0;
883	    } else {
884		height = (height - options.subsampleY - 1)
885			/ -options.subsampleY;
886	    }
887	    options.toY2 = options.toY + height * options.zoomY;
888	}
889
890	/*
891	 * Set the destination image size if the -shrink option was specified.
892	 */
893
894	if (options.options & OPT_SHRINK) {
895	    if (ImgPhotoSetSize(masterPtr, options.toX2,
896		    options.toY2) != TCL_OK) {
897		Tcl_ResetResult(interp);
898		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
899			TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
900		return TCL_ERROR;
901	    }
902	}
903
904	/*
905	 * Copy the image data over using Tk_PhotoPutZoomedBlock.
906	 */
907
908	block.pixelPtr += options.fromX * block.pixelSize
909		+ options.fromY * block.pitch;
910	block.width = options.fromX2 - options.fromX;
911	block.height = options.fromY2 - options.fromY;
912	Tk_PhotoPutZoomedBlock((Tk_PhotoHandle) masterPtr, &block,
913		options.toX, options.toY, options.toX2 - options.toX,
914		options.toY2 - options.toY, options.zoomX, options.zoomY,
915		options.subsampleX, options.subsampleY,
916		options.compositingRule);
917	return TCL_OK;
918
919    case PHOTO_DATA: {
920	char *data;
921
922	/*
923	 * photo data command - first parse and check any options given.
924	 */
925	Tk_ImageStringWriteProc *stringWriteProc = NULL;
926
927	index = 2;
928	memset((VOID *) &options, 0, sizeof(options));
929	options.name = NULL;
930	options.format = NULL;
931	options.fromX = 0;
932	options.fromY = 0;
933	if (ParseSubcommandOptions(&options, interp,
934		OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
935		&index, objc, objv) != TCL_OK) {
936	    return TCL_ERROR;
937	}
938	if ((options.name != NULL) || (index < objc)) {
939	    Tcl_WrongNumArgs(interp, 2, objv, "?options?");
940	    return TCL_ERROR;
941	}
942	if ((options.fromX > masterPtr->width)
943		|| (options.fromY > masterPtr->height)
944		|| (options.fromX2 > masterPtr->width)
945		|| (options.fromY2 > masterPtr->height)) {
946	    Tcl_AppendResult(interp, "coordinates for -from option extend ",
947		    "outside image", (char *) NULL);
948	    return TCL_ERROR;
949	}
950
951	/*
952	 * Fill in default values for unspecified parameters.
953	 */
954
955	if (((options.options & OPT_FROM) == 0) || (options.fromX2 < 0)) {
956	    options.fromX2 = masterPtr->width;
957	    options.fromY2 = masterPtr->height;
958	}
959
960	/*
961	 * Search for an appropriate image string format handler.
962	 */
963
964	if (options.options & OPT_FORMAT) {
965	    matched = 0;
966	    for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
967	 	imageFormat = imageFormat->nextPtr) {
968		if ((strncasecmp(Tcl_GetString(options.format),
969			imageFormat->name, strlen(imageFormat->name)) == 0)) {
970		    matched = 1;
971		    if (imageFormat->stringWriteProc != NULL) {
972			stringWriteProc = imageFormat->stringWriteProc;
973			break;
974		    }
975		}
976	    }
977	    if (stringWriteProc == NULL) {
978		oldformat = 1;
979		for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
980			imageFormat = imageFormat->nextPtr) {
981		    if ((strncasecmp(Tcl_GetString(options.format),
982			    imageFormat->name,
983			    strlen(imageFormat->name)) == 0)) {
984			matched = 1;
985			if (imageFormat->stringWriteProc != NULL) {
986			    stringWriteProc = imageFormat->stringWriteProc;
987			    break;
988			}
989		    }
990		}
991	    }
992	    if (stringWriteProc == NULL) {
993		Tcl_AppendResult(interp, "image string format \"",
994			Tcl_GetString(options.format), "\" is ",
995			(matched ? "not supported" : "unknown"),
996			(char *) NULL);
997		return TCL_ERROR;
998	    }
999	} else {
1000	    stringWriteProc = ImgStringWrite;
1001	}
1002
1003	/*
1004	 * Call the handler's string write procedure to write out
1005	 * the image.
1006	 */
1007
1008	data = ImgGetPhoto(masterPtr, &block, &options);
1009
1010	if (oldformat) {
1011	    Tcl_DString buffer;
1012
1013	    Tcl_DStringInit(&buffer);
1014	    result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp,
1015		    Tcl_DString *buffer, char *formatString,
1016		    Tk_PhotoImageBlock *blockPtr))) stringWriteProc)
1017		    (interp, &buffer, Tcl_GetString(options.format), &block);
1018	    if (result == TCL_OK) {
1019		Tcl_DStringResult(interp, &buffer);
1020	    } else {
1021		Tcl_DStringFree(&buffer);
1022	    }
1023	} else {
1024	    result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp,
1025		    Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr,
1026		    VOID *dummy))) stringWriteProc)
1027		    (interp, options.format, &block, (VOID *) NULL);
1028	}
1029	if (options.background) {
1030	    Tk_FreeColor(options.background);
1031	}
1032	if (data) {
1033	    ckfree(data);
1034	}
1035	return result;
1036    }
1037
1038    case PHOTO_GET: {
1039	/*
1040	 * photo get command - first parse and check parameters.
1041	 */
1042
1043	char string[TCL_INTEGER_SPACE * 3];
1044
1045	if (objc != 4) {
1046	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
1047	    return TCL_ERROR;
1048	}
1049	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
1050		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
1051	    return TCL_ERROR;
1052	}
1053	if ((x < 0) || (x >= masterPtr->width)
1054		|| (y < 0) || (y >= masterPtr->height)) {
1055	    Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " get: ",
1056		    "coordinates out of range", (char *) NULL);
1057	    return TCL_ERROR;
1058	}
1059
1060	/*
1061	 * Extract the value of the desired pixel and format it as a string.
1062	 */
1063
1064	pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
1065	sprintf(string, "%d %d %d", pixelPtr[0], pixelPtr[1],
1066		pixelPtr[2]);
1067	Tcl_AppendResult(interp, string, (char *) NULL);
1068	return TCL_OK;
1069    }
1070
1071    case PHOTO_PUT:
1072	/*
1073	 * photo put command - first parse the options and colors specified.
1074	 */
1075
1076	index = 2;
1077	memset((VOID *) &options, 0, sizeof(options));
1078	options.name = NULL;
1079	if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT,
1080		&index, objc, objv) != TCL_OK) {
1081	    return TCL_ERROR;
1082	}
1083	if ((options.name == NULL) || (index < objc)) {
1084	    Tcl_WrongNumArgs(interp, 2, objv, "data ?options?");
1085	    return TCL_ERROR;
1086	}
1087
1088	if (MatchStringFormat(interp, options.name ? objv[2]:NULL,
1089		options.format, &imageFormat, &imageWidth,
1090		&imageHeight, &oldformat) == TCL_OK) {
1091	    Tcl_Obj *format, *data;
1092
1093	    if (((options.options & OPT_TO) == 0) || (options.toX2 < 0)) {
1094		options.toX2 = options.toX + imageWidth;
1095		options.toY2 = options.toY + imageHeight;
1096	    }
1097	    if (imageWidth > options.toX2 - options.toX) {
1098		imageWidth = options.toX2 - options.toX;
1099	    }
1100	    if (imageHeight > options.toY2 - options.toY) {
1101		imageHeight = options.toY2 - options.toY;
1102	    }
1103	    format = options.format;
1104	    data = objv[2];
1105	    if (oldformat) {
1106		if (format) {
1107		    format = (Tcl_Obj *) Tcl_GetString(format);
1108		}
1109		data = (Tcl_Obj *) Tcl_GetString(data);
1110	    }
1111	    if ((*imageFormat->stringReadProc)(interp, data,
1112		    format, (Tk_PhotoHandle) masterPtr,
1113		    options.toX, options.toY, imageWidth, imageHeight,
1114		    0, 0) != TCL_OK) {
1115		return TCL_ERROR;
1116	    }
1117	    masterPtr->flags |= IMAGE_CHANGED;
1118	    return TCL_OK;
1119	}
1120	if (options.options & OPT_FORMAT) {
1121	    return TCL_ERROR;
1122	}
1123	Tcl_ResetResult(interp);
1124	if (Tcl_SplitList(interp, Tcl_GetString(options.name),
1125		&dataHeight, &srcArgv) != TCL_OK) {
1126	    return TCL_ERROR;
1127	}
1128	tkwin = Tk_MainWindow(interp);
1129	block.pixelPtr = NULL;
1130	dataWidth = 0;
1131	pixelPtr = NULL;
1132	for (y = 0; y < dataHeight; ++y) {
1133	    if (Tcl_SplitList(interp, srcArgv[y], &listArgc, &listArgv)
1134		    != TCL_OK) {
1135		break;
1136	    }
1137	    if (y == 0) {
1138		if (listArgc == 0) {
1139		    /*
1140		     * Lines must be non-empty...
1141		     */
1142		    break;
1143		}
1144		dataWidth = listArgc;
1145		pixelPtr = (unsigned char *)
1146			ckalloc((unsigned) dataWidth * dataHeight * 3);
1147		block.pixelPtr = pixelPtr;
1148	    } else if (listArgc != dataWidth) {
1149		Tcl_AppendResult(interp, "all elements of color list must",
1150			" have the same number of elements", (char *) NULL);
1151		ckfree((char *) listArgv);
1152		break;
1153	    }
1154	    for (x = 0; x < dataWidth; ++x) {
1155		if (!XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
1156			listArgv[x], &color)) {
1157		    Tcl_AppendResult(interp, "can't parse color \"",
1158			    listArgv[x], "\"", (char *) NULL);
1159		    break;
1160		}
1161		*pixelPtr++ = color.red >> 8;
1162		*pixelPtr++ = color.green >> 8;
1163		*pixelPtr++ = color.blue >> 8;
1164	    }
1165	    ckfree((char *) listArgv);
1166	    if (x < dataWidth) {
1167		break;
1168	    }
1169	}
1170	ckfree((char *) srcArgv);
1171	if (y < dataHeight || dataHeight == 0 || dataWidth == 0) {
1172	    if (block.pixelPtr != NULL) {
1173		ckfree((char *) block.pixelPtr);
1174	    }
1175	    if (y < dataHeight) {
1176		return TCL_ERROR;
1177	    }
1178	    return TCL_OK;
1179	}
1180
1181	/*
1182	 * Fill in default values for the -to option, then
1183	 * copy the block in using Tk_PhotoPutBlock.
1184	 */
1185
1186	if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
1187	    options.toX2 = options.toX + dataWidth;
1188	    options.toY2 = options.toY + dataHeight;
1189	}
1190	block.width = dataWidth;
1191	block.height = dataHeight;
1192	block.pitch = dataWidth * 3;
1193	block.pixelSize = 3;
1194	block.offset[0] = 0;
1195	block.offset[1] = 1;
1196	block.offset[2] = 2;
1197	block.offset[3] = 0;
1198	Tk_PhotoPutBlock((ClientData)masterPtr, &block,
1199		options.toX, options.toY, options.toX2 - options.toX,
1200		options.toY2 - options.toY, TK_PHOTO_COMPOSITE_SET);
1201	ckfree((char *) block.pixelPtr);
1202	return TCL_OK;
1203
1204    case PHOTO_READ: {
1205	Tcl_Obj *format;
1206
1207	/*
1208	 * photo read command - first parse the options specified.
1209	 */
1210
1211	index = 2;
1212	memset((VOID *) &options, 0, sizeof(options));
1213	options.name = NULL;
1214	options.format = NULL;
1215	if (ParseSubcommandOptions(&options, interp,
1216		OPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK,
1217		&index, objc, objv) != TCL_OK) {
1218	    return TCL_ERROR;
1219	}
1220	if ((options.name == NULL) || (index < objc)) {
1221	    Tcl_WrongNumArgs(interp, 2, objv, "fileName ?options?");
1222	    return TCL_ERROR;
1223	}
1224
1225        /*
1226         * Prevent file system access in safe interpreters.
1227         */
1228
1229        if (Tcl_IsSafe(interp)) {
1230            Tcl_AppendResult(interp, "can't get image from a file in a",
1231		    " safe interpreter", (char *) NULL);
1232            return TCL_ERROR;
1233        }
1234
1235	/*
1236	 * Open the image file and look for a handler for it.
1237	 */
1238
1239	chan = Tcl_OpenFileChannel(interp,
1240		Tcl_GetString(options.name), "r", 0);
1241	if (chan == NULL) {
1242	    return TCL_ERROR;
1243	}
1244        if (Tcl_SetChannelOption(interp, chan, "-translation", "binary")
1245		!= TCL_OK) {
1246	    Tcl_Close(NULL, chan);
1247            return TCL_ERROR;
1248        }
1249        if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary")
1250		!= TCL_OK) {
1251	    Tcl_Close(NULL, chan);
1252            return TCL_ERROR;
1253        }
1254
1255	if (MatchFileFormat(interp, chan,
1256		Tcl_GetString(options.name), options.format, &imageFormat,
1257		&imageWidth, &imageHeight, &oldformat) != TCL_OK) {
1258	    Tcl_Close(NULL, chan);
1259	    return TCL_ERROR;
1260	}
1261
1262	/*
1263	 * Check the values given for the -from option.
1264	 */
1265
1266	if ((options.fromX > imageWidth) || (options.fromY > imageHeight)
1267		|| (options.fromX2 > imageWidth)
1268		|| (options.fromY2 > imageHeight)) {
1269	    Tcl_AppendResult(interp, "coordinates for -from option extend ",
1270		    "outside source image", (char *) NULL);
1271	    Tcl_Close(NULL, chan);
1272	    return TCL_ERROR;
1273	}
1274	if (((options.options & OPT_FROM) == 0) || (options.fromX2 < 0)) {
1275	    width = imageWidth - options.fromX;
1276	    height = imageHeight - options.fromY;
1277	} else {
1278	    width = options.fromX2 - options.fromX;
1279	    height = options.fromY2 - options.fromY;
1280	}
1281
1282	/*
1283	 * If the -shrink option was specified, set the size of the image.
1284	 */
1285
1286	if (options.options & OPT_SHRINK) {
1287	    if (ImgPhotoSetSize(masterPtr, options.toX + width,
1288		    options.toY + height) != TCL_OK) {
1289		Tcl_ResetResult(interp);
1290		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1291			TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
1292		return TCL_ERROR;
1293	    }
1294	}
1295
1296	/*
1297	 * Call the handler's file read procedure to read the data
1298	 * into the image.
1299	 */
1300
1301	format = options.format;
1302	if (oldformat && format) {
1303	    format = (Tcl_Obj *) Tcl_GetString(format);
1304	}
1305	result = (*imageFormat->fileReadProc)(interp, chan,
1306		Tcl_GetString(options.name),
1307		format, (Tk_PhotoHandle) masterPtr, options.toX,
1308		options.toY, width, height, options.fromX, options.fromY);
1309	if (chan != NULL) {
1310	    Tcl_Close(NULL, chan);
1311	}
1312	return result;
1313    }
1314
1315    case PHOTO_REDITHER:
1316	if (objc != 2) {
1317	    Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
1318	    return TCL_ERROR;
1319	}
1320
1321	/*
1322	 * Call Dither if any part of the image is not correctly
1323	 * dithered at present.
1324	 */
1325
1326	x = masterPtr->ditherX;
1327	y = masterPtr->ditherY;
1328	if (masterPtr->ditherX != 0) {
1329	    Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y,
1330		    masterPtr->width - x, 1);
1331	}
1332	if (masterPtr->ditherY < masterPtr->height) {
1333	    x = 0;
1334	    Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, 0,
1335		    masterPtr->ditherY, masterPtr->width,
1336		    masterPtr->height - masterPtr->ditherY);
1337	}
1338
1339	if (y < masterPtr->height) {
1340	    /*
1341	     * Tell the core image code that part of the image has changed.
1342	     */
1343
1344	    Tk_ImageChanged(masterPtr->tkMaster, x, y,
1345		    (masterPtr->width - x), (masterPtr->height - y),
1346		    masterPtr->width, masterPtr->height);
1347	}
1348	return TCL_OK;
1349
1350    case PHOTO_TRANS: {
1351	static CONST char *photoTransOptions[] = {
1352	    "get", "set", (char *) NULL
1353	};
1354	enum transOptions {
1355	    PHOTO_TRANS_GET, PHOTO_TRANS_SET
1356	};
1357
1358	if (objc < 3) {
1359	    Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
1360	    return TCL_ERROR;
1361	}
1362	if (Tcl_GetIndexFromObj(interp, objv[2], photoTransOptions, "option",
1363		0, &index) != TCL_OK) {
1364	    return TCL_ERROR;
1365	}
1366
1367	switch ((enum transOptions) index) {
1368	case PHOTO_TRANS_GET: {
1369	    XRectangle testBox;
1370	    TkRegion testRegion;
1371
1372	    if (objc != 5) {
1373		Tcl_WrongNumArgs(interp, 3, objv, "x y");
1374		return TCL_ERROR;
1375	    }
1376	    if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
1377		    || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {
1378		return TCL_ERROR;
1379	    }
1380	    if ((x < 0) || (x >= masterPtr->width)
1381		|| (y < 0) || (y >= masterPtr->height)) {
1382		Tcl_AppendResult(interp, Tcl_GetString(objv[0]),
1383			" transparency get: coordinates out of range",
1384			(char *) NULL);
1385		return TCL_ERROR;
1386	    }
1387
1388	    testBox.x = x;
1389	    testBox.y = y;
1390	    testBox.width = 1;
1391	    testBox.height = 1;
1392	    /* What a way to do a test! */
1393	    testRegion = TkCreateRegion();
1394	    TkUnionRectWithRegion(&testBox, testRegion, testRegion);
1395	    TkIntersectRegion(testRegion, masterPtr->validRegion, testRegion);
1396	    TkClipBox(testRegion, &testBox);
1397	    TkDestroyRegion(testRegion);
1398
1399	    Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
1400		    (testBox.width==0 && testBox.height==0));
1401	    return TCL_OK;
1402	}
1403
1404	case PHOTO_TRANS_SET: {
1405	    int transFlag;
1406	    XRectangle setBox;
1407
1408	    if (objc != 6) {
1409		Tcl_WrongNumArgs(interp, 3, objv, "x y boolean");
1410		return TCL_ERROR;
1411	    }
1412	    if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
1413		    || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)
1414		    || (Tcl_GetBooleanFromObj(interp, objv[5],
1415		    &transFlag) != TCL_OK)) {
1416		return TCL_ERROR;
1417	    }
1418	    if ((x < 0) || (x >= masterPtr->width)
1419		|| (y < 0) || (y >= masterPtr->height)) {
1420		Tcl_AppendResult(interp, Tcl_GetString(objv[0]),
1421			" transparency set: coordinates out of range",
1422			(char *) NULL);
1423		return TCL_ERROR;
1424	    }
1425
1426	    setBox.x = x;
1427	    setBox.y = y;
1428	    setBox.width = 1;
1429	    setBox.height = 1;
1430	    pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
1431
1432	    if (transFlag) {
1433		/*
1434		 * Make pixel transparent.
1435		 */
1436		TkRegion clearRegion = TkCreateRegion();
1437
1438		TkUnionRectWithRegion(&setBox, clearRegion, clearRegion);
1439		TkSubtractRegion(masterPtr->validRegion, clearRegion,
1440			masterPtr->validRegion);
1441		TkDestroyRegion(clearRegion);
1442		/*
1443		 * Set the alpha value correctly.
1444		 */
1445		pixelPtr[3] = 0;
1446	    } else {
1447		/*
1448		 * Make pixel opaque.
1449		 */
1450		TkUnionRectWithRegion(&setBox, masterPtr->validRegion,
1451			masterPtr->validRegion);
1452		pixelPtr[3] = 255;
1453	    }
1454
1455	    /*
1456	     * Inform the generic image code that the image
1457	     * has (potentially) changed.
1458	     */
1459
1460	    Tk_ImageChanged(masterPtr->tkMaster, x, y, 1, 1,
1461		    masterPtr->width, masterPtr->height);
1462	    masterPtr->flags &= ~IMAGE_CHANGED;
1463	    return TCL_OK;
1464	}
1465	}
1466
1467	panic("unexpected fallthrough");
1468    }
1469
1470    case PHOTO_WRITE: {
1471	char *data;
1472	Tcl_Obj *format;
1473
1474        /*
1475         * Prevent file system access in safe interpreters.
1476         */
1477
1478        if (Tcl_IsSafe(interp)) {
1479            Tcl_AppendResult(interp, "can't write image to a file in a",
1480		    " safe interpreter", (char *) NULL);
1481            return TCL_ERROR;
1482        }
1483
1484	/*
1485	 * photo write command - first parse and check any options given.
1486	 */
1487
1488	index = 2;
1489	memset((VOID *) &options, 0, sizeof(options));
1490	options.name = NULL;
1491	options.format = NULL;
1492	if (ParseSubcommandOptions(&options, interp,
1493		OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
1494		&index, objc, objv) != TCL_OK) {
1495	    return TCL_ERROR;
1496	}
1497	if ((options.name == NULL) || (index < objc)) {
1498	    Tcl_WrongNumArgs(interp, 2, objv, "fileName ?options?");
1499	    return TCL_ERROR;
1500	}
1501	if ((options.fromX > masterPtr->width)
1502		|| (options.fromY > masterPtr->height)
1503		|| (options.fromX2 > masterPtr->width)
1504		|| (options.fromY2 > masterPtr->height)) {
1505	    Tcl_AppendResult(interp, "coordinates for -from option extend ",
1506		    "outside image", (char *) NULL);
1507	    return TCL_ERROR;
1508	}
1509
1510	/*
1511	 * Fill in default values for unspecified parameters.
1512	 */
1513
1514	if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
1515	    options.fromX2 = masterPtr->width;
1516	    options.fromY2 = masterPtr->height;
1517	}
1518
1519	/*
1520	 * Search for an appropriate image file format handler,
1521	 * and give an error if none is found.
1522	 */
1523
1524	matched = 0;
1525	for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
1526		imageFormat = imageFormat->nextPtr) {
1527	    if ((options.format == NULL)
1528		    || (strncasecmp(Tcl_GetString(options.format),
1529		    imageFormat->name, strlen(imageFormat->name)) == 0)) {
1530		matched = 1;
1531		if (imageFormat->fileWriteProc != NULL) {
1532		    break;
1533		}
1534	    }
1535	}
1536	if (imageFormat == NULL) {
1537	    oldformat = 1;
1538	    for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
1539		    imageFormat = imageFormat->nextPtr) {
1540		if ((options.format == NULL)
1541			|| (strncasecmp(Tcl_GetString(options.format),
1542			imageFormat->name, strlen(imageFormat->name)) == 0)) {
1543		    matched = 1;
1544		    if (imageFormat->fileWriteProc != NULL) {
1545			break;
1546		    }
1547		}
1548	    }
1549	}
1550	if (imageFormat == NULL) {
1551	    if (options.format == NULL) {
1552		Tcl_AppendResult(interp, "no available image file format ",
1553			"has file writing capability", (char *) NULL);
1554	    } else if (!matched) {
1555		Tcl_AppendResult(interp, "image file format \"",
1556			Tcl_GetString(options.format),
1557			"\" is unknown", (char *) NULL);
1558	    } else {
1559		Tcl_AppendResult(interp, "image file format \"",
1560			Tcl_GetString(options.format),
1561			"\" has no file writing capability",
1562			(char *) NULL);
1563	    }
1564	    return TCL_ERROR;
1565	}
1566
1567	/*
1568	 * Call the handler's file write procedure to write out
1569	 * the image.
1570	 */
1571
1572	data = ImgGetPhoto(masterPtr, &block, &options);
1573	format = options.format;
1574	if (oldformat && format) {
1575	    format = (Tcl_Obj *) Tcl_GetString(options.format);
1576	}
1577	result = (*imageFormat->fileWriteProc)(interp,
1578		Tcl_GetString(options.name), format, &block);
1579	if (options.background) {
1580	    Tk_FreeColor(options.background);
1581	}
1582	if (data) {
1583	    ckfree(data);
1584	}
1585	return result;
1586    }
1587
1588    }
1589    panic("unexpected fallthrough");
1590    return TCL_ERROR; /* NOT REACHED */
1591}
1592
1593/*
1594 *----------------------------------------------------------------------
1595 *
1596 * ParseSubcommandOptions --
1597 *
1598 *	This procedure is invoked to process one of the options
1599 *	which may be specified for the photo image subcommands,
1600 *	namely, -from, -to, -zoom, -subsample, -format, -shrink,
1601 *	and -compositingrule.
1602 *
1603 * Results:
1604 *	A standard Tcl result.
1605 *
1606 * Side effects:
1607 *	Fields in *optPtr get filled in.
1608 *
1609 *----------------------------------------------------------------------
1610 */
1611
1612static int
1613ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv)
1614    struct SubcommandOptions *optPtr;
1615				/* Information about the options specified
1616				 * and the values given is returned here. */
1617    Tcl_Interp *interp;		/* Interpreter to use for reporting errors. */
1618    int allowedOptions;		/* Indicates which options are valid for
1619				 * the current command. */
1620    int *optIndexPtr;		/* Points to a variable containing the
1621				 * current index in objv; this variable is
1622				 * updated by this procedure. */
1623    int objc;			/* Number of arguments in objv[]. */
1624    Tcl_Obj *CONST objv[];	/* Arguments to be parsed. */
1625{
1626    int index, c, bit, currentBit;
1627    int length;
1628    char *option, **listPtr;
1629    int values[4];
1630    int numValues, maxValues, argIndex;
1631
1632    for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) {
1633	/*
1634	 * We can have one value specified without an option;
1635	 * it goes into optPtr->name.
1636	 */
1637
1638	option = Tcl_GetStringFromObj(objv[index], &length);
1639	if (option[0] != '-') {
1640	    if (optPtr->name == NULL) {
1641		optPtr->name = objv[index];
1642		continue;
1643	    }
1644	    break;
1645	}
1646
1647	/*
1648	 * Work out which option this is.
1649	 */
1650
1651	c = option[0];
1652	bit = 0;
1653	currentBit = 1;
1654	for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {
1655	    if ((c == *listPtr[0])
1656		    && (strncmp(option, *listPtr, (size_t) length) == 0)) {
1657		if (bit != 0) {
1658		    bit = 0;	/* An ambiguous option. */
1659		    break;
1660		}
1661		bit = currentBit;
1662	    }
1663	    currentBit <<= 1;
1664	}
1665
1666	/*
1667	 * If this option is not recognized and allowed, put
1668	 * an error message in the interpreter and return.
1669	 */
1670
1671	if ((allowedOptions & bit) == 0) {
1672	    Tcl_AppendResult(interp, "unrecognized option \"",
1673	    	    Tcl_GetString(objv[index]),
1674		    "\": must be ", (char *)NULL);
1675	    bit = 1;
1676	    for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {
1677		if ((allowedOptions & bit) != 0) {
1678		    if ((allowedOptions & (bit - 1)) != 0) {
1679			Tcl_AppendResult(interp, ", ", (char *) NULL);
1680			if ((allowedOptions & ~((bit << 1) - 1)) == 0) {
1681			    Tcl_AppendResult(interp, "or ", (char *) NULL);
1682			}
1683		    }
1684		    Tcl_AppendResult(interp, *listPtr, (char *) NULL);
1685		}
1686		bit <<= 1;
1687	    }
1688	    return TCL_ERROR;
1689	}
1690
1691	/*
1692	 * For the -from, -to, -zoom and -subsample options,
1693	 * parse the values given.  Report an error if too few
1694	 * or too many values are given.
1695	 */
1696
1697	if (bit == OPT_BACKGROUND) {
1698	    /*
1699	     * The -background option takes a single XColor value.
1700	     */
1701
1702	    if (index + 1 < objc) {
1703		*optIndexPtr = ++index;
1704		optPtr->background = Tk_GetColor(interp, Tk_MainWindow(interp),
1705			Tk_GetUid(Tcl_GetString(objv[index])));
1706		if (!optPtr->background) {
1707		    return TCL_ERROR;
1708		}
1709	    } else {
1710		Tcl_AppendResult(interp, "the \"-background\" option ",
1711			"requires a value", (char *) NULL);
1712		return TCL_ERROR;
1713	    }
1714	} else if (bit == OPT_FORMAT) {
1715	    /*
1716	     * The -format option takes a single string value.  Note
1717	     * that parsing this is outside the scope of this
1718	     * function.
1719	     */
1720
1721	    if (index + 1 < objc) {
1722		*optIndexPtr = ++index;
1723		optPtr->format = objv[index];
1724	    } else {
1725		Tcl_AppendResult(interp, "the \"-format\" option ",
1726			"requires a value", (char *) NULL);
1727		return TCL_ERROR;
1728	    }
1729	} else if (bit == OPT_COMPOSITE) {
1730	    /*
1731	     * The -compositingrule option takes a single value from
1732	     * a well-known set.
1733	     */
1734
1735	    if (index + 1 < objc) {
1736		/*
1737		 * Note that these must match the TK_PHOTO_COMPOSITE_*
1738		 * constants.
1739		 */
1740		static CONST char *compositingRules[] = {
1741		    "overlay", "set",
1742		    NULL
1743		};
1744
1745		index++;
1746		if (Tcl_GetIndexFromObj(interp, objv[index], compositingRules,
1747			"compositing rule", 0, &optPtr->compositingRule)
1748			!= TCL_OK) {
1749		    return TCL_ERROR;
1750		}
1751		*optIndexPtr = index;
1752	    } else {
1753		Tcl_AppendResult(interp, "the \"-compositingrule\" option ",
1754			"requires a value", (char *) NULL);
1755		return TCL_ERROR;
1756	    }
1757	} else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) {
1758	    char *val;
1759	    maxValues = ((bit == OPT_FROM) || (bit == OPT_TO))? 4: 2;
1760	    argIndex = index + 1;
1761	    for (numValues = 0; numValues < maxValues; ++numValues) {
1762		if (argIndex >= objc) {
1763		    break;
1764		}
1765	        val = Tcl_GetString(objv[argIndex]);
1766		if ((argIndex < objc) && (isdigit(UCHAR(val[0]))
1767			|| ((val[0] == '-') && isdigit(UCHAR(val[1]))))) {
1768		    if (Tcl_GetInt(interp, val, &values[numValues])
1769			    != TCL_OK) {
1770			return TCL_ERROR;
1771		    }
1772		} else {
1773		    break;
1774		}
1775		++argIndex;
1776	    }
1777
1778	    if (numValues == 0) {
1779		Tcl_AppendResult(interp, "the \"", option, "\" option ",
1780			 "requires one ", maxValues == 2? "or two": "to four",
1781			 " integer values", (char *) NULL);
1782		return TCL_ERROR;
1783	    }
1784	    *optIndexPtr = (index += numValues);
1785
1786	    /*
1787	     * Y values default to the corresponding X value if not specified.
1788	     */
1789
1790	    if (numValues == 1) {
1791		values[1] = values[0];
1792	    }
1793	    if (numValues == 3) {
1794		values[3] = values[2];
1795	    }
1796
1797	    /*
1798	     * Check the values given and put them in the appropriate
1799	     * field of the SubcommandOptions structure.
1800	     */
1801
1802	    switch (bit) {
1803		case OPT_FROM:
1804		    if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2)
1805			    && ((values[2] < 0) || (values[3] < 0)))) {
1806			Tcl_AppendResult(interp, "value(s) for the -from",
1807				" option must be non-negative", (char *) NULL);
1808			return TCL_ERROR;
1809		    }
1810		    if (numValues <= 2) {
1811			optPtr->fromX = values[0];
1812			optPtr->fromY = values[1];
1813			optPtr->fromX2 = -1;
1814			optPtr->fromY2 = -1;
1815		    } else {
1816			optPtr->fromX = MIN(values[0], values[2]);
1817			optPtr->fromY = MIN(values[1], values[3]);
1818			optPtr->fromX2 = MAX(values[0], values[2]);
1819			optPtr->fromY2 = MAX(values[1], values[3]);
1820		    }
1821		    break;
1822		case OPT_SUBSAMPLE:
1823		    optPtr->subsampleX = values[0];
1824		    optPtr->subsampleY = values[1];
1825		    break;
1826		case OPT_TO:
1827		    if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2)
1828			    && ((values[2] < 0) || (values[3] < 0)))) {
1829			Tcl_AppendResult(interp, "value(s) for the -to",
1830				" option must be non-negative", (char *) NULL);
1831			return TCL_ERROR;
1832		    }
1833		    if (numValues <= 2) {
1834			optPtr->toX = values[0];
1835			optPtr->toY = values[1];
1836			optPtr->toX2 = -1;
1837			optPtr->toY2 = -1;
1838		    } else {
1839			optPtr->toX = MIN(values[0], values[2]);
1840			optPtr->toY = MIN(values[1], values[3]);
1841			optPtr->toX2 = MAX(values[0], values[2]);
1842			optPtr->toY2 = MAX(values[1], values[3]);
1843		    }
1844		    break;
1845		case OPT_ZOOM:
1846		    if ((values[0] <= 0) || (values[1] <= 0)) {
1847			Tcl_AppendResult(interp, "value(s) for the -zoom",
1848				" option must be positive", (char *) NULL);
1849			return TCL_ERROR;
1850		    }
1851		    optPtr->zoomX = values[0];
1852		    optPtr->zoomY = values[1];
1853		    break;
1854	    }
1855	}
1856
1857	/*
1858	 * Remember that we saw this option.
1859	 */
1860
1861	optPtr->options |= bit;
1862    }
1863
1864    return TCL_OK;
1865}
1866
1867/*
1868 *----------------------------------------------------------------------
1869 *
1870 * ImgPhotoConfigureMaster --
1871 *
1872 *	This procedure is called when a photo image is created or
1873 *	reconfigured.  It processes configuration options and resets
1874 *	any instances of the image.
1875 *
1876 * Results:
1877 *	A standard Tcl return value.  If TCL_ERROR is returned then
1878 *	an error message is left in the masterPtr->interp's result.
1879 *
1880 * Side effects:
1881 *	Existing instances of the image will be redisplayed to match
1882 *	the new configuration options.
1883 *
1884 *----------------------------------------------------------------------
1885 */
1886
1887static int
1888ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags)
1889    Tcl_Interp *interp;		/* Interpreter to use for reporting errors. */
1890    PhotoMaster *masterPtr;	/* Pointer to data structure describing
1891				 * overall photo image to (re)configure. */
1892    int objc;			/* Number of entries in objv. */
1893    Tcl_Obj *CONST objv[];	/* Pairs of configuration options for image. */
1894    int flags;			/* Flags to pass to Tk_ConfigureWidget,
1895				 * such as TK_CONFIG_ARGV_ONLY. */
1896{
1897    PhotoInstance *instancePtr;
1898    CONST char *oldFileString, *oldPaletteString;
1899    Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL;
1900    int length, i, j;
1901    double oldGamma;
1902    int result;
1903    Tcl_Channel chan;
1904    Tk_PhotoImageFormat *imageFormat;
1905    int imageWidth, imageHeight;
1906    CONST char **args;
1907    int oldformat;
1908    Tcl_Obj *tempdata, *tempformat;
1909
1910    args = (CONST char **) ckalloc((objc + 1) * sizeof(char *));
1911    for (i = 0, j = 0; i < objc; i++,j++) {
1912	args[j] = Tcl_GetStringFromObj(objv[i], &length);
1913	if ((length > 1) && (args[j][0] == '-')) {
1914	    if ((args[j][1] == 'd') &&
1915		    !strncmp(args[j], "-data", (size_t) length)) {
1916		if (++i < objc) {
1917		    data = objv[i];
1918		    j--;
1919		} else {
1920		    Tcl_AppendResult(interp,
1921			    "value for \"-data\" missing", (char *) NULL);
1922		    return TCL_ERROR;
1923		}
1924	    } else if ((args[j][1] == 'f') &&
1925		    !strncmp(args[j], "-format", (size_t) length)) {
1926		if (++i < objc) {
1927		    format = objv[i];
1928		    j--;
1929		} else {
1930		    Tcl_AppendResult(interp,
1931			    "value for \"-format\" missing", (char *) NULL);
1932		    return TCL_ERROR;
1933		}
1934	    }
1935	}
1936    }
1937
1938    /*
1939     * Save the current values for fileString and dataString, so we
1940     * can tell if the user specifies them anew.
1941     * IMPORTANT: if the format changes we have to interpret
1942     * "-file" and "-data" again as well!!!!!!! It might be
1943     * that the format string influences how "-data" or "-file"
1944     * is interpreted.
1945     */
1946
1947    oldFileString = masterPtr->fileString;
1948    if (oldFileString == NULL) {
1949	oldData = masterPtr->dataString;
1950	if (oldData != NULL) {
1951	    Tcl_IncrRefCount(oldData);
1952	}
1953    } else {
1954	oldData = NULL;
1955    }
1956    oldFormat = masterPtr->format;
1957    if (oldFormat != NULL) {
1958	Tcl_IncrRefCount(oldFormat);
1959    }
1960    oldPaletteString = masterPtr->palette;
1961    oldGamma = masterPtr->gamma;
1962
1963    /*
1964     * Process the configuration options specified.
1965     */
1966
1967    if (Tk_ConfigureWidget(interp, Tk_MainWindow(interp), configSpecs,
1968	    j, args, (char *) masterPtr, flags) != TCL_OK) {
1969	ckfree((char *) args);
1970	goto errorExit;
1971    }
1972    ckfree((char *) args);
1973
1974    /*
1975     * Regard the empty string for -file, -data or -format as the null
1976     * value.
1977     */
1978
1979    if ((masterPtr->fileString != NULL) && (masterPtr->fileString[0] == 0)) {
1980	ckfree(masterPtr->fileString);
1981	masterPtr->fileString = NULL;
1982    }
1983    if (data) {
1984	/*
1985	 * Force into ByteArray format, which most (all) image handlers
1986	 * will use anyway.  Empty length means ignore the -data option.
1987	 */
1988	(void) Tcl_GetByteArrayFromObj(data, &length);
1989	if (length) {
1990	    Tcl_IncrRefCount(data);
1991	} else {
1992	    data = NULL;
1993	}
1994	if (masterPtr->dataString) {
1995	    Tcl_DecrRefCount(masterPtr->dataString);
1996	}
1997	masterPtr->dataString = data;
1998    }
1999    if (format) {
2000	/*
2001	 * Stringify to ignore -format "".  It may come in as a list or
2002	 * other object.
2003	 */
2004	(void) Tcl_GetStringFromObj(format, &length);
2005	if (length) {
2006	    Tcl_IncrRefCount(format);
2007	} else {
2008	    format = NULL;
2009	}
2010	if (masterPtr->format) {
2011	    Tcl_DecrRefCount(masterPtr->format);
2012	}
2013	masterPtr->format = format;
2014    }
2015    /*
2016     * Set the image to the user-requested size, if any,
2017     * and make sure storage is correctly allocated for this image.
2018     */
2019
2020    if (ImgPhotoSetSize(masterPtr, masterPtr->width,
2021	    masterPtr->height) != TCL_OK) {
2022	Tcl_ResetResult(interp);
2023	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2024		TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
2025	goto errorExit;
2026    }
2027
2028    /*
2029     * Read in the image from the file or string if the user has
2030     * specified the -file or -data option.
2031     */
2032
2033    if ((masterPtr->fileString != NULL)
2034	    && ((masterPtr->fileString != oldFileString)
2035	    || (masterPtr->format != oldFormat))) {
2036
2037        /*
2038         * Prevent file system access in a safe interpreter.
2039         */
2040
2041        if (Tcl_IsSafe(interp)) {
2042	    Tcl_ResetResult(interp);
2043            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2044		    "can't get image from a file in a safe interpreter",
2045		    (char *) NULL);
2046	    goto errorExit;
2047        }
2048
2049	chan = Tcl_OpenFileChannel(interp, masterPtr->fileString, "r", 0);
2050	if (chan == NULL) {
2051	    goto errorExit;
2052	}
2053	/*
2054	 * -translation binary also sets -encoding binary
2055	 */
2056        if ((Tcl_SetChannelOption(interp, chan,
2057		"-translation", "binary") != TCL_OK) ||
2058		(MatchFileFormat(interp, chan, masterPtr->fileString,
2059			masterPtr->format, &imageFormat, &imageWidth,
2060			&imageHeight, &oldformat) != TCL_OK)) {
2061	    Tcl_Close(NULL, chan);
2062	    goto errorExit;
2063	}
2064	result = ImgPhotoSetSize(masterPtr, imageWidth, imageHeight);
2065	if (result != TCL_OK) {
2066	    Tcl_Close(NULL, chan);
2067	    Tcl_ResetResult(interp);
2068	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2069		    TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
2070	    goto errorExit;
2071	}
2072	tempformat = masterPtr->format;
2073	if (oldformat && tempformat) {
2074	    tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
2075	}
2076	result = (*imageFormat->fileReadProc)(interp, chan,
2077		masterPtr->fileString, tempformat,
2078		(Tk_PhotoHandle) masterPtr, 0, 0,
2079		imageWidth, imageHeight, 0, 0);
2080	Tcl_Close(NULL, chan);
2081	if (result != TCL_OK) {
2082	    goto errorExit;
2083	}
2084
2085	Tcl_ResetResult(interp);
2086	masterPtr->flags |= IMAGE_CHANGED;
2087    }
2088
2089    if ((masterPtr->fileString == NULL) && (masterPtr->dataString != NULL)
2090	    && ((masterPtr->dataString != oldData)
2091		    || (masterPtr->format != oldFormat))) {
2092
2093	if (MatchStringFormat(interp, masterPtr->dataString,
2094		masterPtr->format, &imageFormat, &imageWidth,
2095		&imageHeight, &oldformat) != TCL_OK) {
2096	    goto errorExit;
2097	}
2098	if (ImgPhotoSetSize(masterPtr, imageWidth, imageHeight) != TCL_OK) {
2099	    Tcl_ResetResult(interp);
2100	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2101		    TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL);
2102	    goto errorExit;
2103	}
2104	tempformat = masterPtr->format;
2105	tempdata = masterPtr->dataString;
2106	if (oldformat) {
2107	    if (tempformat) {
2108		tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
2109	    }
2110	    tempdata = (Tcl_Obj *) Tcl_GetString(tempdata);
2111	}
2112	if ((*imageFormat->stringReadProc)(interp, tempdata,
2113		tempformat, (Tk_PhotoHandle) masterPtr,
2114		0, 0, imageWidth, imageHeight, 0, 0) != TCL_OK) {
2115	    goto errorExit;
2116	}
2117
2118	Tcl_ResetResult(interp);
2119	masterPtr->flags |= IMAGE_CHANGED;
2120    }
2121
2122    /*
2123     * Enforce a reasonable value for gamma.
2124     */
2125
2126    if (masterPtr->gamma <= 0) {
2127	masterPtr->gamma = 1.0;
2128    }
2129
2130    if ((masterPtr->gamma != oldGamma)
2131	    || (masterPtr->palette != oldPaletteString)) {
2132	masterPtr->flags |= IMAGE_CHANGED;
2133    }
2134
2135    /*
2136     * Cycle through all of the instances of this image, regenerating
2137     * the information for each instance.  Then force the image to be
2138     * redisplayed everywhere that it is used.
2139     */
2140
2141    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
2142	    instancePtr = instancePtr->nextPtr) {
2143	ImgPhotoConfigureInstance(instancePtr);
2144    }
2145
2146    /*
2147     * Inform the generic image code that the image
2148     * has (potentially) changed.
2149     */
2150
2151    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
2152	    masterPtr->height, masterPtr->width, masterPtr->height);
2153    masterPtr->flags &= ~IMAGE_CHANGED;
2154
2155    if (oldData != NULL) {
2156	Tcl_DecrRefCount(oldData);
2157    }
2158    if (oldFormat != NULL) {
2159	Tcl_DecrRefCount(oldFormat);
2160    }
2161
2162    ToggleComplexAlphaIfNeeded(masterPtr);
2163
2164    return TCL_OK;
2165
2166  errorExit:
2167    if (oldData != NULL) {
2168	Tcl_DecrRefCount(oldData);
2169    }
2170    if (oldFormat != NULL) {
2171	Tcl_DecrRefCount(oldFormat);
2172    }
2173    return TCL_ERROR;
2174}
2175
2176/*
2177 *----------------------------------------------------------------------
2178 *
2179 * ImgPhotoConfigureInstance --
2180 *
2181 *	This procedure is called to create displaying information for
2182 *	a photo image instance based on the configuration information
2183 *	in the master.  It is invoked both when new instances are
2184 *	created and when the master is reconfigured.
2185 *
2186 * Results:
2187 *	None.
2188 *
2189 * Side effects:
2190 *	Generates errors via Tcl_BackgroundError if there are problems
2191 *	in setting up the instance.
2192 *
2193 *----------------------------------------------------------------------
2194 */
2195
2196static void
2197ImgPhotoConfigureInstance(instancePtr)
2198    PhotoInstance *instancePtr;	/* Instance to reconfigure. */
2199{
2200    PhotoMaster *masterPtr = instancePtr->masterPtr;
2201    XImage *imagePtr;
2202    int bitsPerPixel;
2203    ColorTable *colorTablePtr;
2204    XRectangle validBox;
2205
2206    /*
2207     * If the -palette configuration option has been set for the master,
2208     * use the value specified for our palette, but only if it is
2209     * a valid palette for our windows.  Use the gamma value specified
2210     * the master.
2211     */
2212
2213    if ((masterPtr->palette && masterPtr->palette[0])
2214	    && IsValidPalette(instancePtr, masterPtr->palette)) {
2215	instancePtr->palette = masterPtr->palette;
2216    } else {
2217	instancePtr->palette = instancePtr->defaultPalette;
2218    }
2219    instancePtr->gamma = masterPtr->gamma;
2220
2221    /*
2222     * If we don't currently have a color table, or if the one we
2223     * have no longer applies (e.g. because our palette or gamma
2224     * has changed), get a new one.
2225     */
2226
2227    colorTablePtr = instancePtr->colorTablePtr;
2228    if ((colorTablePtr == NULL)
2229	    || (instancePtr->colormap != colorTablePtr->id.colormap)
2230	    || (instancePtr->palette != colorTablePtr->id.palette)
2231	    || (instancePtr->gamma != colorTablePtr->id.gamma)) {
2232	/*
2233	 * Free up our old color table, and get a new one.
2234	 */
2235
2236	if (colorTablePtr != NULL) {
2237	    colorTablePtr->liveRefCount -= 1;
2238	    FreeColorTable(colorTablePtr, 0);
2239	}
2240	GetColorTable(instancePtr);
2241
2242	/*
2243	 * Create a new XImage structure for sending data to
2244	 * the X server, if necessary.
2245	 */
2246
2247	if (instancePtr->colorTablePtr->flags & BLACK_AND_WHITE) {
2248	    bitsPerPixel = 1;
2249	} else {
2250	    bitsPerPixel = instancePtr->visualInfo.depth;
2251	}
2252
2253	if ((instancePtr->imagePtr == NULL)
2254		|| (instancePtr->imagePtr->bits_per_pixel != bitsPerPixel)) {
2255	    if (instancePtr->imagePtr != NULL) {
2256		XDestroyImage(instancePtr->imagePtr);
2257	    }
2258	    imagePtr = XCreateImage(instancePtr->display,
2259		    instancePtr->visualInfo.visual, (unsigned) bitsPerPixel,
2260		    (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, (char *) NULL,
2261		    1, 1, 32, 0);
2262	    instancePtr->imagePtr = imagePtr;
2263
2264	    /*
2265	     * We create images using the local host's endianness, rather than
2266	     * the endianness of the server; otherwise we would have to
2267	     * byte-swap any 16 or 32 bit values that we store in the image
2268	     * if the server's endianness is different from ours.
2269	     */
2270
2271	    if (imagePtr != NULL) {
2272#ifdef WORDS_BIGENDIAN
2273		imagePtr->byte_order = MSBFirst;
2274#else
2275		imagePtr->byte_order = LSBFirst;
2276#endif
2277		_XInitImageFuncPtrs(imagePtr);
2278	    }
2279	}
2280    }
2281
2282    /*
2283     * If the user has specified a width and/or height for the master
2284     * which is different from our current width/height, set the size
2285     * to the values specified by the user.  If we have no pixmap, we
2286     * do this also, since it has the side effect of allocating a
2287     * pixmap for us.
2288     */
2289
2290    if ((instancePtr->pixels == None) || (instancePtr->error == NULL)
2291	    || (instancePtr->width != masterPtr->width)
2292	    || (instancePtr->height != masterPtr->height)) {
2293	ImgPhotoInstanceSetSize(instancePtr);
2294    }
2295
2296    /*
2297     * Redither this instance if necessary.
2298     */
2299
2300    if ((masterPtr->flags & IMAGE_CHANGED)
2301	    || (instancePtr->colorTablePtr != colorTablePtr)) {
2302	TkClipBox(masterPtr->validRegion, &validBox);
2303	if ((validBox.width > 0) && (validBox.height > 0)) {
2304	    DitherInstance(instancePtr, validBox.x, validBox.y,
2305		    validBox.width, validBox.height);
2306	}
2307    }
2308}
2309
2310/*
2311 *----------------------------------------------------------------------
2312 *
2313 * ImgPhotoGet --
2314 *
2315 *	This procedure is called for each use of a photo image in a
2316 *	widget.
2317 *
2318 * Results:
2319 *	The return value is a token for the instance, which is passed
2320 *	back to us in calls to ImgPhotoDisplay and ImgPhotoFree.
2321 *
2322 * Side effects:
2323 *	A data structure is set up for the instance (or, an existing
2324 *	instance is re-used for the new one).
2325 *
2326 *----------------------------------------------------------------------
2327 */
2328
2329static ClientData
2330ImgPhotoGet(tkwin, masterData)
2331    Tk_Window tkwin;		/* Window in which the instance will be
2332				 * used. */
2333    ClientData masterData;	/* Pointer to our master structure for the
2334				 * image. */
2335{
2336    PhotoMaster *masterPtr = (PhotoMaster *) masterData;
2337    PhotoInstance *instancePtr;
2338    Colormap colormap;
2339    int mono, nRed, nGreen, nBlue;
2340    XVisualInfo visualInfo, *visInfoPtr;
2341    char buf[TCL_INTEGER_SPACE * 3];
2342    int numVisuals;
2343    XColor *white, *black;
2344    XGCValues gcValues;
2345
2346    /*
2347     * Table of "best" choices for palette for PseudoColor displays
2348     * with between 3 and 15 bits/pixel.
2349     */
2350
2351    static int paletteChoice[13][3] = {
2352	/*  #red, #green, #blue */
2353	 {2,  2,  2,			/* 3 bits, 8 colors */},
2354	 {2,  3,  2,			/* 4 bits, 12 colors */},
2355	 {3,  4,  2,			/* 5 bits, 24 colors */},
2356	 {4,  5,  3,			/* 6 bits, 60 colors */},
2357	 {5,  6,  4,			/* 7 bits, 120 colors */},
2358	 {7,  7,  4,			/* 8 bits, 198 colors */},
2359	 {8, 10,  6,			/* 9 bits, 480 colors */},
2360	{10, 12,  8,			/* 10 bits, 960 colors */},
2361	{14, 15,  9,			/* 11 bits, 1890 colors */},
2362	{16, 20, 12,			/* 12 bits, 3840 colors */},
2363	{20, 24, 16,			/* 13 bits, 7680 colors */},
2364	{26, 30, 20,			/* 14 bits, 15600 colors */},
2365	{32, 32, 30,			/* 15 bits, 30720 colors */}
2366    };
2367
2368    /*
2369     * See if there is already an instance for windows using
2370     * the same colormap.  If so then just re-use it.
2371     */
2372
2373    colormap = Tk_Colormap(tkwin);
2374    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
2375	    instancePtr = instancePtr->nextPtr) {
2376	if ((colormap == instancePtr->colormap)
2377		&& (Tk_Display(tkwin) == instancePtr->display)) {
2378
2379	    /*
2380	     * Re-use this instance.
2381	     */
2382
2383	    if (instancePtr->refCount == 0) {
2384		/*
2385		 * We are resurrecting this instance.
2386		 */
2387
2388		Tcl_CancelIdleCall(DisposeInstance, (ClientData) instancePtr);
2389		if (instancePtr->colorTablePtr != NULL) {
2390		    FreeColorTable(instancePtr->colorTablePtr, 0);
2391		}
2392		GetColorTable(instancePtr);
2393	    }
2394	    instancePtr->refCount++;
2395	    return (ClientData) instancePtr;
2396	}
2397    }
2398
2399    /*
2400     * The image isn't already in use in a window with the same colormap.
2401     * Make a new instance of the image.
2402     */
2403
2404    instancePtr = (PhotoInstance *) ckalloc(sizeof(PhotoInstance));
2405    instancePtr->masterPtr = masterPtr;
2406    instancePtr->display = Tk_Display(tkwin);
2407    instancePtr->colormap = Tk_Colormap(tkwin);
2408    Tk_PreserveColormap(instancePtr->display, instancePtr->colormap);
2409    instancePtr->refCount = 1;
2410    instancePtr->colorTablePtr = NULL;
2411    instancePtr->pixels = None;
2412    instancePtr->error = NULL;
2413    instancePtr->width = 0;
2414    instancePtr->height = 0;
2415    instancePtr->imagePtr = 0;
2416    instancePtr->nextPtr = masterPtr->instancePtr;
2417    masterPtr->instancePtr = instancePtr;
2418
2419    /*
2420     * Obtain information about the visual and decide on the
2421     * default palette.
2422     */
2423
2424    visualInfo.screen = Tk_ScreenNumber(tkwin);
2425    visualInfo.visualid = XVisualIDFromVisual(Tk_Visual(tkwin));
2426    visInfoPtr = XGetVisualInfo(Tk_Display(tkwin),
2427	    VisualScreenMask | VisualIDMask, &visualInfo, &numVisuals);
2428    nRed = 2;
2429    nGreen = nBlue = 0;
2430    mono = 1;
2431    if (visInfoPtr != NULL) {
2432	instancePtr->visualInfo = *visInfoPtr;
2433	switch (visInfoPtr->class) {
2434	    case DirectColor:
2435	    case TrueColor:
2436		nRed = 1 << CountBits(visInfoPtr->red_mask);
2437		nGreen = 1 << CountBits(visInfoPtr->green_mask);
2438		nBlue = 1 << CountBits(visInfoPtr->blue_mask);
2439		mono = 0;
2440		break;
2441	    case PseudoColor:
2442	    case StaticColor:
2443		if (visInfoPtr->depth > 15) {
2444		    nRed = 32;
2445		    nGreen = 32;
2446		    nBlue = 32;
2447		    mono = 0;
2448		} else if (visInfoPtr->depth >= 3) {
2449		    int *ip = paletteChoice[visInfoPtr->depth - 3];
2450
2451		    nRed = ip[0];
2452		    nGreen = ip[1];
2453		    nBlue = ip[2];
2454		    mono = 0;
2455		}
2456		break;
2457	    case GrayScale:
2458	    case StaticGray:
2459		nRed = 1 << visInfoPtr->depth;
2460		break;
2461	}
2462	XFree((char *) visInfoPtr);
2463
2464    } else {
2465	panic("ImgPhotoGet couldn't find visual for window");
2466    }
2467
2468    sprintf(buf, ((mono) ? "%d": "%d/%d/%d"), nRed, nGreen, nBlue);
2469    instancePtr->defaultPalette = Tk_GetUid(buf);
2470
2471    /*
2472     * Make a GC with background = black and foreground = white.
2473     */
2474
2475    white = Tk_GetColor(masterPtr->interp, tkwin, "white");
2476    black = Tk_GetColor(masterPtr->interp, tkwin, "black");
2477    gcValues.foreground = (white != NULL)? white->pixel:
2478	    WhitePixelOfScreen(Tk_Screen(tkwin));
2479    gcValues.background = (black != NULL)? black->pixel:
2480	    BlackPixelOfScreen(Tk_Screen(tkwin));
2481    Tk_FreeColor(white);
2482    Tk_FreeColor(black);
2483    gcValues.graphics_exposures = False;
2484    instancePtr->gc = Tk_GetGC(tkwin,
2485	    GCForeground|GCBackground|GCGraphicsExposures, &gcValues);
2486
2487    /*
2488     * Set configuration options and finish the initialization of the instance.
2489     * This will also dither the image if necessary.
2490     */
2491
2492    ImgPhotoConfigureInstance(instancePtr);
2493
2494    /*
2495     * If this is the first instance, must set the size of the image.
2496     */
2497
2498    if (instancePtr->nextPtr == NULL) {
2499	Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
2500		masterPtr->width, masterPtr->height);
2501    }
2502
2503    return (ClientData) instancePtr;
2504}
2505
2506/*
2507 *----------------------------------------------------------------------
2508 *
2509 * ToggleComplexAlphaIfNeeded --
2510 *
2511 *	This procedure is called when an image is modified to
2512 *	check if any partially transparent pixels exist, which
2513 *	requires blending instead of straight copy.
2514 *
2515 * Results:
2516 *	None.
2517 *
2518 * Side effects:
2519 *	(Re)sets COMPLEX_ALPHA flag of master.
2520 *
2521 *----------------------------------------------------------------------
2522 */
2523
2524static int
2525ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr)
2526{
2527    size_t len = MAX(mPtr->userWidth, mPtr->width) *
2528	MAX(mPtr->userHeight, mPtr->height) * 4;
2529    unsigned char *c   = mPtr->pix32;
2530    unsigned char *end = c + len;
2531
2532    /*
2533     * Set the COMPLEX_ALPHA flag if we have an image with partially
2534     * transparent bits.
2535     */
2536    mPtr->flags &= ~COMPLEX_ALPHA;
2537    c += 3; /* start at first alpha byte */
2538    for (; c < end; c += 4) {
2539	if (*c && *c != 255) {
2540     	    mPtr->flags |= COMPLEX_ALPHA;
2541	    break;
2542	}
2543    }
2544    return (mPtr->flags & COMPLEX_ALPHA);
2545}
2546
2547/*
2548 *----------------------------------------------------------------------
2549 *
2550 * ImgPhotoBlendComplexAlpha --
2551 *
2552 *	This procedure is called when an image with partially
2553 *	transparent pixels must be drawn over another image.
2554 *
2555 * Results:
2556 *	None.
2557 *
2558 * Side effects:
2559 *	Background image passed in gets drawn over with image data.
2560 *
2561 *----------------------------------------------------------------------
2562 */
2563
2564/*
2565 * This should work on all platforms that set mask and shift data properly
2566 * from the visualInfo.
2567 * RGB is really only a 24+ bpp version whereas RGB15 is the correct version
2568 * and works for 15bpp+, but it slower, so it's only used for 15bpp+.
2569 *
2570 * Note that Win32 pre-defines those operations that we really need.
2571 */
2572
2573#ifndef __WIN32__
2574#define GetRValue(rgb)	(UCHAR((rgb & red_mask) >> red_shift))
2575#define GetGValue(rgb)	(UCHAR((rgb & green_mask) >> green_shift))
2576#define GetBValue(rgb)	(UCHAR((rgb & blue_mask) >> blue_shift))
2577#define RGB(r,g,b)      ((unsigned)((UCHAR(r)<<red_shift)|(UCHAR(g)<<green_shift)|(UCHAR(b)<<blue_shift)))
2578#define RGB15(r,g,b)    ((unsigned)(((r*red_mask/255)&red_mask)|((g*green_mask/255)&green_mask)|((b*blue_mask/255)&blue_mask)))
2579#endif /* !__WIN32__ */
2580
2581static void
2582ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height)
2583    XImage *bgImg;		/* background image to draw on */
2584    PhotoInstance *iPtr;	/* image instance to draw */
2585    int xOffset, yOffset;	/* X & Y offset into image instance to draw */
2586    int width, height;		/* width & height of image to draw */
2587{
2588    int x, y, line;
2589    unsigned long pixel;
2590    unsigned char r, g, b, alpha, unalpha;
2591    unsigned char *alphaAr = iPtr->masterPtr->pix32;
2592    unsigned char *masterPtr;
2593
2594    /*
2595     * This blending is an integer version of the Source-Over
2596     * compositing rule (see Porter&Duff, "Compositing Digital
2597     * Images", proceedings of SIGGRAPH 1984) that has been hard-coded
2598     * (for speed) to work with targetting a solid surface.
2599     */
2600
2601#define ALPHA_BLEND(bgPix, imgPix, alpha, unalpha) \
2602	((bgPix * unalpha + imgPix * alpha) / 255)
2603
2604    /*
2605     * We have to get the mask and shift info from the visual on
2606     * non-Win32 so that the macros Get*Value(), RGB() and RGB15()
2607     * work correctly.  This might be cached for better performance.
2608     */
2609
2610#ifndef __WIN32__
2611    unsigned long red_mask, green_mask, blue_mask;
2612    unsigned long red_shift, green_shift, blue_shift;
2613    Visual *visual = iPtr->visualInfo.visual;
2614
2615    red_mask = visual->red_mask;
2616    green_mask = visual->green_mask;
2617    blue_mask = visual->blue_mask;
2618    red_shift = 0;
2619    green_shift = 0;
2620    blue_shift = 0;
2621    while ((0x0001 & (red_mask >> red_shift)) == 0) {
2622	red_shift++;
2623    }
2624    while ((0x0001 & (green_mask >> green_shift)) == 0) {
2625	green_shift++;
2626    }
2627    while ((0x0001 & (blue_mask >> blue_shift)) == 0) {
2628	blue_shift++;
2629    }
2630#endif /* !__WIN32__ */
2631
2632    /*
2633     * Only unix requires the special case for <24bpp.  It varies with
2634     * 3 extra shifts and uses RGB15.  The 24+bpp version could also
2635     * then be further optimized.
2636     */
2637
2638#if !(defined(__WIN32__) || defined(MAC_OSX_TK))
2639    if (bgImg->depth < 24) {
2640	unsigned char red_mlen, green_mlen, blue_mlen;
2641
2642	red_mlen = 8 - CountBits(red_mask >> red_shift);
2643	green_mlen = 8 - CountBits(green_mask >> green_shift);
2644	blue_mlen = 8 - CountBits(blue_mask >> blue_shift);
2645	for (y = 0; y < height; y++) {
2646	    line = (y + yOffset) * iPtr->masterPtr->width;
2647	    for (x = 0; x < width; x++) {
2648		masterPtr = alphaAr + ((line + x + xOffset) * 4);
2649		alpha = masterPtr[3];
2650		/*
2651		 * Ignore pixels that are fully transparent
2652		 */
2653		if (alpha) {
2654		    /*
2655		     * We could perhaps be more efficient than XGetPixel for
2656		     * 24 and 32 bit displays, but this seems "fast enough".
2657		     */
2658		    r = masterPtr[0];
2659		    g = masterPtr[1];
2660		    b = masterPtr[2];
2661		    if (alpha != 255) {
2662			/*
2663			 * Only blend pixels that have some transparency
2664			 */
2665			unsigned char ra, ga, ba;
2666
2667			pixel = XGetPixel(bgImg, x, y);
2668			ra = GetRValue(pixel) << red_mlen;
2669			ga = GetGValue(pixel) << green_mlen;
2670			ba = GetBValue(pixel) << blue_mlen;
2671			unalpha = 255 - alpha;
2672			r = ALPHA_BLEND(ra, r, alpha, unalpha);
2673			g = ALPHA_BLEND(ga, g, alpha, unalpha);
2674			b = ALPHA_BLEND(ba, b, alpha, unalpha);
2675		    }
2676		    XPutPixel(bgImg, x, y, RGB15(r, g, b));
2677		}
2678	    }
2679	}
2680	return;
2681    }
2682#endif /* !__WIN32__ && !MAC_OSX_TK */
2683
2684    for (y = 0; y < height; y++) {
2685	line = (y + yOffset) * iPtr->masterPtr->width;
2686	for (x = 0; x < width; x++) {
2687	    masterPtr = alphaAr + ((line + x + xOffset) * 4);
2688	    alpha = masterPtr[3];
2689	    /*
2690	     * Ignore pixels that are fully transparent
2691	     */
2692	    if (alpha) {
2693		/*
2694		 * We could perhaps be more efficient than XGetPixel for
2695		 * 24 and 32 bit displays, but this seems "fast enough".
2696		 */
2697		r = masterPtr[0];
2698		g = masterPtr[1];
2699		b = masterPtr[2];
2700		if (alpha != 255) {
2701		    /*
2702		     * Only blend pixels that have some transparency
2703		     */
2704		    unsigned char ra, ga, ba;
2705
2706		    pixel = XGetPixel(bgImg, x, y);
2707		    ra = GetRValue(pixel);
2708		    ga = GetGValue(pixel);
2709		    ba = GetBValue(pixel);
2710		    unalpha = 255 - alpha;
2711		    r = ALPHA_BLEND(ra, r, alpha, unalpha);
2712		    g = ALPHA_BLEND(ga, g, alpha, unalpha);
2713		    b = ALPHA_BLEND(ba, b, alpha, unalpha);
2714		}
2715		XPutPixel(bgImg, x, y, RGB(r, g, b));
2716	    }
2717	}
2718    }
2719
2720#undef ALPHA_BLEND
2721}
2722
2723/*
2724 *----------------------------------------------------------------------
2725 *
2726 * ImgPhotoDisplay --
2727 *
2728 *	This procedure is invoked to draw a photo image.
2729 *
2730 * Results:
2731 *	None.
2732 *
2733 * Side effects:
2734 *	A portion of the image gets rendered in a pixmap or window.
2735 *
2736 *----------------------------------------------------------------------
2737 */
2738
2739static void
2740ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width,
2741	height, drawableX, drawableY)
2742    ClientData clientData;	/* Pointer to PhotoInstance structure for
2743				 * for instance to be displayed. */
2744    Display *display;		/* Display on which to draw image. */
2745    Drawable drawable;		/* Pixmap or window in which to draw image. */
2746    int imageX, imageY;		/* Upper-left corner of region within image
2747				 * to draw. */
2748    int width, height;		/* Dimensions of region within image to draw. */
2749    int drawableX, drawableY;	/* Coordinates within drawable that
2750				 * correspond to imageX and imageY. */
2751{
2752    PhotoInstance *instancePtr = (PhotoInstance *) clientData;
2753    XVisualInfo visInfo = instancePtr->visualInfo;
2754
2755    /*
2756     * If there's no pixmap, it means that an error occurred
2757     * while creating the image instance so it can't be displayed.
2758     */
2759
2760    if (instancePtr->pixels == None) {
2761	return;
2762    }
2763
2764    /*
2765     * Check for bogus widths/heights.  This prevents us from calling
2766     * XGetImage with a zero size, which it does not like. [Bug 979239]
2767     */
2768
2769    if (width < 1 || height < 1) {
2770	return;
2771    }
2772
2773    if (
2774#if defined(MAC_TCL)
2775	/*
2776	 * The retrieval of bgImg is currently not functional on OS9
2777	 * so skip attempts to alpha blend.
2778	 */
2779	0 &&
2780#endif
2781	(instancePtr->masterPtr->flags & COMPLEX_ALPHA)
2782	    && visInfo.depth >= 15
2783	    && (visInfo.class == DirectColor || visInfo.class == TrueColor)) {
2784	Tk_ErrorHandler handler;
2785	XImage *bgImg = NULL;
2786
2787	/*
2788	 * Create an error handler to suppress the case where the input was
2789	 * not properly constrained, which can cause an X error. [Bug 979239]
2790	 */
2791	handler = Tk_CreateErrorHandler(display, -1, -1, -1,
2792		(Tk_ErrorProc *) NULL, (ClientData) NULL);
2793	/*
2794	 * Pull the current background from the display to blend with
2795	 */
2796	bgImg = XGetImage(display, drawable, drawableX, drawableY,
2797		(unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
2798	if (bgImg == NULL) {
2799	    Tk_DeleteErrorHandler(handler);
2800	    return;
2801	}
2802
2803	ImgPhotoBlendComplexAlpha(bgImg, instancePtr,
2804		imageX, imageY, width, height);
2805
2806	/*
2807	 * Color info is unimportant as we only do this operation for
2808	 * depth >= 15.
2809	 */
2810	TkPutImage(NULL, 0, display, drawable, instancePtr->gc,
2811		bgImg, 0, 0, drawableX, drawableY,
2812		(unsigned int) width, (unsigned int) height);
2813	XDestroyImage(bgImg);
2814	Tk_DeleteErrorHandler(handler);
2815    } else {
2816	/*
2817	 * masterPtr->region describes which parts of the image contain
2818	 * valid data.  We set this region as the clip mask for the gc,
2819	 * setting its origin appropriately, and use it when drawing the
2820	 * image.
2821	 */
2822	TkSetRegion(display, instancePtr->gc, instancePtr->masterPtr->validRegion);
2823	XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
2824	               drawableY - imageY);
2825	XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc,
2826	          imageX, imageY, (unsigned) width, (unsigned) height,
2827	          drawableX, drawableY);
2828	XSetClipMask(display, instancePtr->gc, None);
2829	XSetClipOrigin(display, instancePtr->gc, 0, 0);
2830    }
2831    XFlush (display);
2832}
2833
2834/*
2835 *----------------------------------------------------------------------
2836 *
2837 * ImgPhotoFree --
2838 *
2839 *	This procedure is called when a widget ceases to use a
2840 *	particular instance of an image.  We don't actually get
2841 *	rid of the instance until later because we may be about
2842 *	to get this instance again.
2843 *
2844 * Results:
2845 *	None.
2846 *
2847 * Side effects:
2848 *	Internal data structures get cleaned up, later.
2849 *
2850 *----------------------------------------------------------------------
2851 */
2852
2853static void
2854ImgPhotoFree(clientData, display)
2855    ClientData clientData;	/* Pointer to PhotoInstance structure for
2856				 * for instance to be displayed. */
2857    Display *display;		/* Display containing window that used image. */
2858{
2859    PhotoInstance *instancePtr = (PhotoInstance *) clientData;
2860    ColorTable *colorPtr;
2861
2862    instancePtr->refCount -= 1;
2863    if (instancePtr->refCount > 0) {
2864	return;
2865    }
2866
2867    /*
2868     * There are no more uses of the image within this widget.
2869     * Decrement the count of live uses of its color table, so
2870     * that its colors can be reclaimed if necessary, and
2871     * set up an idle call to free the instance structure.
2872     */
2873
2874    colorPtr = instancePtr->colorTablePtr;
2875    if (colorPtr != NULL) {
2876	colorPtr->liveRefCount -= 1;
2877    }
2878
2879    Tcl_DoWhenIdle(DisposeInstance, (ClientData) instancePtr);
2880}
2881
2882/*
2883 *----------------------------------------------------------------------
2884 *
2885 * ImgPhotoDelete --
2886 *
2887 *	This procedure is called by the image code to delete the
2888 *	master structure for an image.
2889 *
2890 * Results:
2891 *	None.
2892 *
2893 * Side effects:
2894 *	Resources associated with the image get freed.
2895 *
2896 *----------------------------------------------------------------------
2897 */
2898
2899static void
2900ImgPhotoDelete(masterData)
2901    ClientData masterData;	/* Pointer to PhotoMaster structure for
2902				 * image.  Must not have any more instances. */
2903{
2904    PhotoMaster *masterPtr = (PhotoMaster *) masterData;
2905    PhotoInstance *instancePtr;
2906
2907    while ((instancePtr = masterPtr->instancePtr) != NULL) {
2908	if (instancePtr->refCount > 0) {
2909	    panic("tried to delete photo image when instances still exist");
2910	}
2911	Tcl_CancelIdleCall(DisposeInstance, (ClientData) instancePtr);
2912	DisposeInstance((ClientData) instancePtr);
2913    }
2914    masterPtr->tkMaster = NULL;
2915    if (masterPtr->imageCmd != NULL) {
2916	Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);
2917    }
2918    if (masterPtr->pix32 != NULL) {
2919	ckfree((char *) masterPtr->pix32);
2920    }
2921    if (masterPtr->validRegion != NULL) {
2922	TkDestroyRegion(masterPtr->validRegion);
2923    }
2924    if (masterPtr->dataString != NULL) {
2925	Tcl_DecrRefCount(masterPtr->dataString);
2926    }
2927    if (masterPtr->format != NULL) {
2928	Tcl_DecrRefCount(masterPtr->format);
2929    }
2930    Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0);
2931    ckfree((char *) masterPtr);
2932}
2933
2934/*
2935 *----------------------------------------------------------------------
2936 *
2937 * ImgPhotoCmdDeletedProc --
2938 *
2939 *	This procedure is invoked when the image command for an image
2940 *	is deleted.  It deletes the image.
2941 *
2942 * Results:
2943 *	None.
2944 *
2945 * Side effects:
2946 *	The image is deleted.
2947 *
2948 *----------------------------------------------------------------------
2949 */
2950
2951static void
2952ImgPhotoCmdDeletedProc(clientData)
2953    ClientData clientData;	/* Pointer to PhotoMaster structure for
2954				 * image. */
2955{
2956    PhotoMaster *masterPtr = (PhotoMaster *) clientData;
2957
2958    masterPtr->imageCmd = NULL;
2959    if (masterPtr->tkMaster != NULL) {
2960	Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
2961    }
2962}
2963
2964/*
2965 *----------------------------------------------------------------------
2966 *
2967 * ImgPhotoSetSize --
2968 *
2969 *	This procedure reallocates the image storage and instance
2970 *	pixmaps for a photo image, as necessary, to change the
2971 *	image's size to `width' x `height' pixels.
2972 *
2973 * Results:
2974 *	TCL_OK if successful, TCL_ERROR if failure occurred (currently
2975 *	just with memory allocation.)
2976 *
2977 * Side effects:
2978 *	Storage gets reallocated, for the master and all its instances.
2979 *
2980 *----------------------------------------------------------------------
2981 */
2982
2983static int
2984ImgPhotoSetSize(masterPtr, width, height)
2985    PhotoMaster *masterPtr;
2986    int width, height;
2987{
2988    unsigned char *newPix32 = NULL;
2989    int h, offset, pitch;
2990    unsigned char *srcPtr, *destPtr;
2991    XRectangle validBox, clipBox;
2992    TkRegion clipRegion;
2993    PhotoInstance *instancePtr;
2994
2995    if (masterPtr->userWidth > 0) {
2996	width = masterPtr->userWidth;
2997    }
2998    if (masterPtr->userHeight > 0) {
2999	height = masterPtr->userHeight;
3000    }
3001
3002    pitch = width * 4;
3003
3004    /*
3005     * Test if we're going to (re)allocate the main buffer now, so
3006     * that any failures will leave the photo unchanged.
3007     */
3008    if ((width != masterPtr->width) || (height != masterPtr->height)
3009	    || (masterPtr->pix32 == NULL)) {
3010	/*
3011	 * Not a u-long, but should be one.
3012	 */
3013	unsigned /*long*/ newPixSize = (unsigned /*long*/) (height * pitch);
3014
3015	/*
3016	 * Some mallocs() really hate allocating zero bytes. [Bug 619544]
3017	 */
3018	if (newPixSize == 0) {
3019	    newPix32 = NULL;
3020	} else {
3021	    newPix32 = (unsigned char *) attemptckalloc(newPixSize);
3022	    if (newPix32 == NULL) {
3023		return TCL_ERROR;
3024	    }
3025	}
3026    }
3027
3028    /*
3029     * We have to trim the valid region if it is currently
3030     * larger than the new image size.
3031     */
3032
3033    TkClipBox(masterPtr->validRegion, &validBox);
3034    if ((validBox.x + validBox.width > width)
3035	    || (validBox.y + validBox.height > height)) {
3036	clipBox.x = 0;
3037	clipBox.y = 0;
3038	clipBox.width = width;
3039	clipBox.height = height;
3040	clipRegion = TkCreateRegion();
3041	TkUnionRectWithRegion(&clipBox, clipRegion, clipRegion);
3042	TkIntersectRegion(masterPtr->validRegion, clipRegion,
3043		masterPtr->validRegion);
3044	TkDestroyRegion(clipRegion);
3045	TkClipBox(masterPtr->validRegion, &validBox);
3046    }
3047
3048    /*
3049     * Use the reallocated storage (allocation above) for the 32-bit
3050     * image and copy over valid regions.  Note that this test is true
3051     * precisely when the allocation has already been done.
3052     */
3053    if (newPix32 != NULL) {
3054	/*
3055	 * Zero the new array.  The dithering code shouldn't read the
3056	 * areas outside validBox, but they might be copied to another
3057	 * photo image or written to a file.
3058	 */
3059
3060	if ((masterPtr->pix32 != NULL)
3061	    && ((width == masterPtr->width) || (width == validBox.width))) {
3062	    if (validBox.y > 0) {
3063		memset((VOID *) newPix32, 0, (size_t) (validBox.y * pitch));
3064	    }
3065	    h = validBox.y + validBox.height;
3066	    if (h < height) {
3067		memset((VOID *) (newPix32 + h * pitch), 0,
3068			(size_t) ((height - h) * pitch));
3069	    }
3070	} else {
3071	    memset((VOID *) newPix32, 0, (size_t) (height * pitch));
3072	}
3073
3074	if (masterPtr->pix32 != NULL) {
3075
3076	    /*
3077	     * Copy the common area over to the new array array and
3078	     * free the old array.
3079	     */
3080
3081	    if (width == masterPtr->width) {
3082
3083		/*
3084		 * The region to be copied is contiguous.
3085		 */
3086
3087		offset = validBox.y * pitch;
3088		memcpy((VOID *) (newPix32 + offset),
3089			(VOID *) (masterPtr->pix32 + offset),
3090			(size_t) (validBox.height * pitch));
3091
3092	    } else if ((validBox.width > 0) && (validBox.height > 0)) {
3093
3094		/*
3095		 * Area to be copied is not contiguous - copy line by line.
3096		 */
3097
3098		destPtr = newPix32 + (validBox.y * width + validBox.x) * 4;
3099		srcPtr = masterPtr->pix32 + (validBox.y * masterPtr->width
3100			+ validBox.x) * 4;
3101		for (h = validBox.height; h > 0; h--) {
3102		    memcpy((VOID *) destPtr, (VOID *) srcPtr,
3103			    (size_t) (validBox.width * 4));
3104		    destPtr += width * 4;
3105		    srcPtr += masterPtr->width * 4;
3106		}
3107	    }
3108
3109	    ckfree((char *) masterPtr->pix32);
3110	}
3111
3112	masterPtr->pix32 = newPix32;
3113	masterPtr->width = width;
3114	masterPtr->height = height;
3115
3116	/*
3117	 * Dithering will be correct up to the end of the last
3118	 * pre-existing complete scanline.
3119	 */
3120
3121	if ((validBox.x > 0) || (validBox.y > 0)) {
3122	    masterPtr->ditherX = 0;
3123	    masterPtr->ditherY = 0;
3124	} else if (validBox.width == width) {
3125	    if ((int) validBox.height < masterPtr->ditherY) {
3126		masterPtr->ditherX = 0;
3127		masterPtr->ditherY = validBox.height;
3128	    }
3129	} else if ((masterPtr->ditherY > 0)
3130		|| ((int) validBox.width < masterPtr->ditherX)) {
3131	    masterPtr->ditherX = validBox.width;
3132	    masterPtr->ditherY = 0;
3133	}
3134    }
3135
3136    ToggleComplexAlphaIfNeeded(masterPtr);
3137
3138    /*
3139     * Now adjust the sizes of the pixmaps for all of the instances.
3140     */
3141
3142    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
3143	    instancePtr = instancePtr->nextPtr) {
3144	ImgPhotoInstanceSetSize(instancePtr);
3145    }
3146
3147    return TCL_OK;
3148}
3149
3150/*
3151 *----------------------------------------------------------------------
3152 *
3153 * ImgPhotoInstanceSetSize --
3154 *
3155 * 	This procedure reallocates the instance pixmap and dithering
3156 *	error array for a photo instance, as necessary, to change the
3157 *	image's size to `width' x `height' pixels.
3158 *
3159 * Results:
3160 *	None.
3161 *
3162 * Side effects:
3163 *	Storage gets reallocated, here and in the X server.
3164 *
3165 *----------------------------------------------------------------------
3166 */
3167
3168static void
3169ImgPhotoInstanceSetSize(instancePtr)
3170    PhotoInstance *instancePtr;		/* Instance whose size is to be
3171					 * changed. */
3172{
3173    PhotoMaster *masterPtr;
3174    schar *newError;
3175    schar *errSrcPtr, *errDestPtr;
3176    int h, offset;
3177    XRectangle validBox;
3178    Pixmap newPixmap;
3179
3180    masterPtr = instancePtr->masterPtr;
3181    TkClipBox(masterPtr->validRegion, &validBox);
3182
3183    if ((instancePtr->width != masterPtr->width)
3184	    || (instancePtr->height != masterPtr->height)
3185	    || (instancePtr->pixels == None)) {
3186	newPixmap = Tk_GetPixmap(instancePtr->display,
3187		RootWindow(instancePtr->display,
3188		    instancePtr->visualInfo.screen),
3189		(masterPtr->width > 0) ? masterPtr->width: 1,
3190		(masterPtr->height > 0) ? masterPtr->height: 1,
3191		instancePtr->visualInfo.depth);
3192        if (!newPixmap) {
3193            panic("Fail to create pixmap with Tk_GetPixmap in ImgPhotoInstanceSetSize.\n");
3194            return;
3195        }
3196
3197	/*
3198	 * The following is a gross hack needed to properly support colormaps
3199	 * under Windows.  Before the pixels can be copied to the pixmap,
3200	 * the relevent colormap must be associated with the drawable.
3201	 * Normally we can infer this association from the window that
3202	 * was used to create the pixmap.  However, in this case we're
3203	 * using the root window, so we have to be more explicit.
3204	 */
3205
3206	TkSetPixmapColormap(newPixmap, instancePtr->colormap);
3207
3208	if (instancePtr->pixels != None) {
3209	    /*
3210	     * Copy any common pixels from the old pixmap and free it.
3211	     */
3212	    XCopyArea(instancePtr->display, instancePtr->pixels, newPixmap,
3213		    instancePtr->gc, validBox.x, validBox.y,
3214		    validBox.width, validBox.height, validBox.x, validBox.y);
3215	    Tk_FreePixmap(instancePtr->display, instancePtr->pixels);
3216	}
3217	instancePtr->pixels = newPixmap;
3218    }
3219
3220    if ((instancePtr->width != masterPtr->width)
3221	    || (instancePtr->height != masterPtr->height)
3222	    || (instancePtr->error == NULL)) {
3223
3224	if (masterPtr->height > 0 && masterPtr->width > 0) {
3225	    newError = (schar *) ckalloc((unsigned)
3226		    masterPtr->height * masterPtr->width * 3 * sizeof(schar));
3227
3228	    /*
3229	     * Zero the new array so that we don't get bogus error
3230	     * values propagating into areas we dither later.
3231	     */
3232
3233	    if ((instancePtr->error != NULL)
3234		    && ((instancePtr->width == masterPtr->width)
3235		    || (validBox.width == masterPtr->width))) {
3236		if (validBox.y > 0) {
3237		    memset((VOID *) newError, 0, (size_t)
3238			    validBox.y * masterPtr->width * 3 * sizeof(schar));
3239		}
3240		h = validBox.y + validBox.height;
3241		if (h < masterPtr->height) {
3242		    memset((VOID *) (newError + h * masterPtr->width * 3), 0,
3243			    (size_t) (masterPtr->height - h)
3244			    * masterPtr->width * 3 * sizeof(schar));
3245		}
3246	    } else {
3247		memset((VOID *) newError, 0, (size_t)
3248			masterPtr->height * masterPtr->width * 3 * sizeof(schar));
3249	    }
3250	} else {
3251	    newError = NULL;
3252	}
3253
3254	if (instancePtr->error != NULL) {
3255
3256	    /*
3257	     * Copy the common area over to the new array
3258	     * and free the old array.
3259	     */
3260
3261	    if (masterPtr->width == instancePtr->width) {
3262
3263		offset = validBox.y * masterPtr->width * 3;
3264		memcpy((VOID *) (newError + offset),
3265			(VOID *) (instancePtr->error + offset),
3266			(size_t) (validBox.height
3267			* masterPtr->width * 3 * sizeof(schar)));
3268
3269	    } else if (validBox.width > 0 && validBox.height > 0) {
3270
3271		errDestPtr = newError
3272			+ (validBox.y * masterPtr->width + validBox.x) * 3;
3273		errSrcPtr = instancePtr->error
3274			+ (validBox.y * instancePtr->width + validBox.x) * 3;
3275		for (h = validBox.height; h > 0; --h) {
3276		    memcpy((VOID *) errDestPtr, (VOID *) errSrcPtr,
3277			    validBox.width * 3 * sizeof(schar));
3278		    errDestPtr += masterPtr->width * 3;
3279		    errSrcPtr += instancePtr->width * 3;
3280		}
3281	    }
3282	    ckfree((char *) instancePtr->error);
3283	}
3284
3285	instancePtr->error = newError;
3286    }
3287
3288    instancePtr->width = masterPtr->width;
3289    instancePtr->height = masterPtr->height;
3290}
3291
3292/*
3293 *----------------------------------------------------------------------
3294 *
3295 * IsValidPalette --
3296 *
3297 *	This procedure is called to check whether a value given for
3298 *	the -palette option is valid for a particular instance
3299 * 	of a photo image.
3300 *
3301 * Results:
3302 *	A boolean value: 1 if the palette is acceptable, 0 otherwise.
3303 *
3304 * Side effects:
3305 *	None.
3306 *
3307 *----------------------------------------------------------------------
3308 */
3309
3310static int
3311IsValidPalette(instancePtr, palette)
3312    PhotoInstance *instancePtr;		/* Instance to which the palette
3313					 * specification is to be applied. */
3314    CONST char *palette;		/* Palette specification string. */
3315{
3316    int nRed, nGreen, nBlue, mono, numColors;
3317    char *endp;
3318
3319    /*
3320     * First parse the specification: it must be of the form
3321     * %d or %d/%d/%d.
3322     */
3323
3324    nRed = strtol(palette, &endp, 10);
3325    if ((endp == palette) || ((*endp != 0) && (*endp != '/'))
3326	    || (nRed < 2) || (nRed > 256)) {
3327	return 0;
3328    }
3329
3330    if (*endp == 0) {
3331	mono = 1;
3332	nGreen = nBlue = nRed;
3333    } else {
3334	palette = endp + 1;
3335	nGreen = strtol(palette, &endp, 10);
3336	if ((endp == palette) || (*endp != '/') || (nGreen < 2)
3337		|| (nGreen > 256)) {
3338	    return 0;
3339	}
3340	palette = endp + 1;
3341	nBlue = strtol(palette, &endp, 10);
3342	if ((endp == palette) || (*endp != 0) || (nBlue < 2)
3343		|| (nBlue > 256)) {
3344	    return 0;
3345	}
3346	mono = 0;
3347    }
3348
3349    switch (instancePtr->visualInfo.class) {
3350	case DirectColor:
3351	case TrueColor:
3352	    if ((nRed > (1 << CountBits(instancePtr->visualInfo.red_mask)))
3353		    || (nGreen > (1
3354			<< CountBits(instancePtr->visualInfo.green_mask)))
3355		    || (nBlue > (1
3356			<< CountBits(instancePtr->visualInfo.blue_mask)))) {
3357		return 0;
3358	    }
3359	    break;
3360	case PseudoColor:
3361	case StaticColor:
3362	    numColors = nRed;
3363	    if (!mono) {
3364		numColors *= nGreen*nBlue;
3365	    }
3366	    if (numColors > (1 << instancePtr->visualInfo.depth)) {
3367		return 0;
3368	    }
3369	    break;
3370	case GrayScale:
3371	case StaticGray:
3372	    if (!mono || (nRed > (1 << instancePtr->visualInfo.depth))) {
3373		return 0;
3374	    }
3375	    break;
3376    }
3377
3378    return 1;
3379}
3380
3381/*
3382 *----------------------------------------------------------------------
3383 *
3384 * CountBits --
3385 *
3386 *	This procedure counts how many bits are set to 1 in `mask'.
3387 *
3388 * Results:
3389 *	The integer number of bits.
3390 *
3391 * Side effects:
3392 *	None.
3393 *
3394 *----------------------------------------------------------------------
3395 */
3396
3397static int
3398CountBits(mask)
3399    pixel mask;			/* Value to count the 1 bits in. */
3400{
3401    int n;
3402
3403    for( n = 0; mask != 0; mask &= mask - 1 )
3404	n++;
3405    return n;
3406}
3407
3408/*
3409 *----------------------------------------------------------------------
3410 *
3411 * GetColorTable --
3412 *
3413 *	This procedure is called to allocate a table of colormap
3414 *	information for an instance of a photo image.  Only one such
3415 *	table is allocated for all photo instances using the same
3416 *	display, colormap, palette and gamma values, so that the
3417 *	application need only request a set of colors from the X
3418 *	server once for all such photo widgets.  This procedure
3419 *	maintains a hash table to find previously-allocated
3420 *	ColorTables.
3421 *
3422 * Results:
3423 *	None.
3424 *
3425 * Side effects:
3426 *	A new ColorTable may be allocated and placed in the hash
3427 *	table, and have colors allocated for it.
3428 *
3429 *----------------------------------------------------------------------
3430 */
3431
3432static void
3433GetColorTable(instancePtr)
3434    PhotoInstance *instancePtr;		/* Instance needing a color table. */
3435{
3436    ColorTable *colorPtr;
3437    Tcl_HashEntry *entry;
3438    ColorTableId id;
3439    int isNew;
3440
3441    /*
3442     * Look for an existing ColorTable in the hash table.
3443     */
3444
3445    memset((VOID *) &id, 0, sizeof(id));
3446    id.display = instancePtr->display;
3447    id.colormap = instancePtr->colormap;
3448    id.palette = instancePtr->palette;
3449    id.gamma = instancePtr->gamma;
3450    if (!imgPhotoColorHashInitialized) {
3451	Tcl_InitHashTable(&imgPhotoColorHash, N_COLOR_HASH);
3452	imgPhotoColorHashInitialized = 1;
3453    }
3454    entry = Tcl_CreateHashEntry(&imgPhotoColorHash, (char *) &id, &isNew);
3455
3456    if (!isNew) {
3457	/*
3458	 * Re-use the existing entry.
3459	 */
3460
3461	colorPtr = (ColorTable *) Tcl_GetHashValue(entry);
3462
3463    } else {
3464	/*
3465	 * No color table currently available; need to make one.
3466	 */
3467
3468	colorPtr = (ColorTable *) ckalloc(sizeof(ColorTable));
3469
3470	/*
3471	 * The following line of code should not normally be needed due
3472	 * to the assignment in the following line.  However, it compensates
3473	 * for bugs in some compilers (HP, for example) where
3474	 * sizeof(ColorTable) is 24 but the assignment only copies 20 bytes,
3475	 * leaving 4 bytes uninitialized;  these cause problems when using
3476	 * the id for lookups in imgPhotoColorHash, and can result in
3477	 * core dumps.
3478	 */
3479
3480	memset((VOID *) &colorPtr->id, 0, sizeof(ColorTableId));
3481	colorPtr->id = id;
3482	Tk_PreserveColormap(colorPtr->id.display, colorPtr->id.colormap);
3483	colorPtr->flags = 0;
3484	colorPtr->refCount = 0;
3485	colorPtr->liveRefCount = 0;
3486	colorPtr->numColors = 0;
3487	colorPtr->visualInfo = instancePtr->visualInfo;
3488	colorPtr->pixelMap = NULL;
3489	Tcl_SetHashValue(entry, colorPtr);
3490    }
3491
3492    colorPtr->refCount++;
3493    colorPtr->liveRefCount++;
3494    instancePtr->colorTablePtr = colorPtr;
3495    if (colorPtr->flags & DISPOSE_PENDING) {
3496	Tcl_CancelIdleCall(DisposeColorTable, (ClientData) colorPtr);
3497	colorPtr->flags &= ~DISPOSE_PENDING;
3498    }
3499
3500    /*
3501     * Allocate colors for this color table if necessary.
3502     */
3503
3504    if ((colorPtr->numColors == 0)
3505	    && ((colorPtr->flags & BLACK_AND_WHITE) == 0)) {
3506	AllocateColors(colorPtr);
3507    }
3508}
3509
3510/*
3511 *----------------------------------------------------------------------
3512 *
3513 * FreeColorTable --
3514 *
3515 *	This procedure is called when an instance ceases using a
3516 *	color table.
3517 *
3518 * Results:
3519 *	None.
3520 *
3521 * Side effects:
3522 *	If no other instances are using this color table, a when-idle
3523 *	handler is registered to free up the color table and the colors
3524 *	allocated for it.
3525 *
3526 *----------------------------------------------------------------------
3527 */
3528
3529static void
3530FreeColorTable(colorPtr, force)
3531    ColorTable *colorPtr;	/* Pointer to the color table which is
3532				 * no longer required by an instance. */
3533    int force;			/* Force free to happen immediately. */
3534{
3535    colorPtr->refCount--;
3536    if (colorPtr->refCount > 0) {
3537	return;
3538    }
3539    if (force) {
3540	if ((colorPtr->flags & DISPOSE_PENDING) != 0) {
3541	    Tcl_CancelIdleCall(DisposeColorTable, (ClientData) colorPtr);
3542	    colorPtr->flags &= ~DISPOSE_PENDING;
3543	}
3544	DisposeColorTable((ClientData) colorPtr);
3545    } else if ((colorPtr->flags & DISPOSE_PENDING) == 0) {
3546	Tcl_DoWhenIdle(DisposeColorTable, (ClientData) colorPtr);
3547	colorPtr->flags |= DISPOSE_PENDING;
3548    }
3549}
3550
3551/*
3552 *----------------------------------------------------------------------
3553 *
3554 * AllocateColors --
3555 *
3556 *	This procedure allocates the colors required by a color table,
3557 *	and sets up the fields in the color table data structure which
3558 *	are used in dithering.
3559 *
3560 * Results:
3561 *	None.
3562 *
3563 * Side effects:
3564 *	Colors are allocated from the X server.  Fields in the
3565 *	color table data structure are updated.
3566 *
3567 *----------------------------------------------------------------------
3568 */
3569
3570static void
3571AllocateColors(colorPtr)
3572    ColorTable *colorPtr;	/* Pointer to the color table requiring
3573				 * colors to be allocated. */
3574{
3575    int i, r, g, b, rMult, mono;
3576    int numColors, nRed, nGreen, nBlue;
3577    double fr, fg, fb, igam;
3578    XColor *colors;
3579    unsigned long *pixels;
3580
3581    /* 16-bit intensity value for i/n of full intensity. */
3582#   define CFRAC(i, n)	((i) * 65535 / (n))
3583
3584    /* As for CFRAC, but apply exponent of g. */
3585#   define CGFRAC(i, n, g)	((int)(65535 * pow((double)(i) / (n), (g))))
3586
3587    /*
3588     * First parse the palette specification to get the required number of
3589     * shades of each primary.
3590     */
3591
3592    mono = sscanf(colorPtr->id.palette, "%d/%d/%d", &nRed, &nGreen, &nBlue)
3593	    <= 1;
3594    igam = 1.0 / colorPtr->id.gamma;
3595
3596    /*
3597     * Each time around this loop, we reduce the number of colors we're
3598     * trying to allocate until we succeed in allocating all of the colors
3599     * we need.
3600     */
3601
3602    for (;;) {
3603	/*
3604	 * If we are using 1 bit/pixel, we don't need to allocate
3605	 * any colors (we just use the foreground and background
3606	 * colors in the GC).
3607	 */
3608
3609	if (mono && (nRed <= 2)) {
3610	    colorPtr->flags |= BLACK_AND_WHITE;
3611	    return;
3612	}
3613
3614	/*
3615	 * Calculate the RGB coordinates of the colors we want to
3616	 * allocate and store them in *colors.
3617	 */
3618
3619	if ((colorPtr->visualInfo.class == DirectColor)
3620	    || (colorPtr->visualInfo.class == TrueColor)) {
3621
3622	    /*
3623	     * Direct/True Color: allocate shades of red, green, blue
3624	     * independently.
3625	     */
3626
3627	    if (mono) {
3628		numColors = nGreen = nBlue = nRed;
3629	    } else {
3630		numColors = MAX(MAX(nRed, nGreen), nBlue);
3631	    }
3632	    colors = (XColor *) ckalloc(numColors * sizeof(XColor));
3633
3634	    for (i = 0; i < numColors; ++i) {
3635		if (igam == 1.0) {
3636		    colors[i].red = CFRAC(i, nRed - 1);
3637		    colors[i].green = CFRAC(i, nGreen - 1);
3638		    colors[i].blue = CFRAC(i, nBlue - 1);
3639		} else {
3640		    colors[i].red = CGFRAC(i, nRed - 1, igam);
3641		    colors[i].green = CGFRAC(i, nGreen - 1, igam);
3642		    colors[i].blue = CGFRAC(i, nBlue - 1, igam);
3643		}
3644	    }
3645	} else {
3646	    /*
3647	     * PseudoColor, StaticColor, GrayScale or StaticGray visual:
3648	     * we have to allocate each color in the color cube separately.
3649	     */
3650
3651	    numColors = (mono) ? nRed: (nRed * nGreen * nBlue);
3652	    colors = (XColor *) ckalloc(numColors * sizeof(XColor));
3653
3654	    if (!mono) {
3655		/*
3656		 * Color display using a PseudoColor or StaticColor visual.
3657		 */
3658
3659		i = 0;
3660		for (r = 0; r < nRed; ++r) {
3661		    for (g = 0; g < nGreen; ++g) {
3662			for (b = 0; b < nBlue; ++b) {
3663			    if (igam == 1.0) {
3664				colors[i].red = CFRAC(r, nRed - 1);
3665				colors[i].green = CFRAC(g, nGreen - 1);
3666				colors[i].blue = CFRAC(b, nBlue - 1);
3667			    } else {
3668				colors[i].red = CGFRAC(r, nRed - 1, igam);
3669				colors[i].green = CGFRAC(g, nGreen - 1, igam);
3670				colors[i].blue = CGFRAC(b, nBlue - 1, igam);
3671			    }
3672			    i++;
3673			}
3674		    }
3675		}
3676	    } else {
3677		/*
3678		 * Monochrome display - allocate the shades of grey we want.
3679		 */
3680
3681		for (i = 0; i < numColors; ++i) {
3682		    if (igam == 1.0) {
3683			r = CFRAC(i, numColors - 1);
3684		    } else {
3685			r = CGFRAC(i, numColors - 1, igam);
3686		    }
3687		    colors[i].red = colors[i].green = colors[i].blue = r;
3688		}
3689	    }
3690	}
3691
3692	/*
3693	 * Now try to allocate the colors we've calculated.
3694	 */
3695
3696	pixels = (unsigned long *) ckalloc(numColors * sizeof(unsigned long));
3697	for (i = 0; i < numColors; ++i) {
3698	    if (!XAllocColor(colorPtr->id.display, colorPtr->id.colormap,
3699		    &colors[i])) {
3700
3701		/*
3702		 * Can't get all the colors we want in the default colormap;
3703		 * first try freeing colors from other unused color tables.
3704		 */
3705
3706		if (!ReclaimColors(&colorPtr->id, numColors - i)
3707			|| !XAllocColor(colorPtr->id.display,
3708			colorPtr->id.colormap, &colors[i])) {
3709		    /*
3710		     * Still can't allocate the color.
3711		     */
3712		    break;
3713		}
3714	    }
3715	    pixels[i] = colors[i].pixel;
3716	}
3717
3718	/*
3719	 * If we didn't get all of the colors, reduce the
3720	 * resolution of the color cube, free the ones we got,
3721	 * and try again.
3722	 */
3723
3724	if (i >= numColors) {
3725	    break;
3726	}
3727	XFreeColors(colorPtr->id.display, colorPtr->id.colormap, pixels, i, 0);
3728	ckfree((char *) colors);
3729	ckfree((char *) pixels);
3730
3731	if (!mono) {
3732	    if ((nRed == 2) && (nGreen == 2) && (nBlue == 2)) {
3733		/*
3734		 * Fall back to 1-bit monochrome display.
3735		 */
3736
3737		mono = 1;
3738	    } else {
3739		/*
3740		 * Reduce the number of shades of each primary to about
3741		 * 3/4 of the previous value.  This should reduce the
3742		 * total number of colors required to about half the
3743		 * previous value for PseudoColor displays.
3744		 */
3745
3746		nRed = (nRed * 3 + 2) / 4;
3747		nGreen = (nGreen * 3 + 2) / 4;
3748		nBlue = (nBlue * 3 + 2) / 4;
3749	    }
3750	} else {
3751	    /*
3752	     * Reduce the number of shades of gray to about 1/2.
3753	     */
3754
3755	    nRed = nRed / 2;
3756	}
3757    }
3758
3759    /*
3760     * We have allocated all of the necessary colors:
3761     * fill in various fields of the ColorTable record.
3762     */
3763
3764    if (!mono) {
3765	colorPtr->flags |= COLOR_WINDOW;
3766
3767	/*
3768	 * The following is a hairy hack.  We only want to index into
3769	 * the pixelMap on colormap displays.  However, if the display
3770	 * is on Windows, then we actually want to store the index not
3771	 * the value since we will be passing the color table into the
3772	 * TkPutImage call.
3773	 */
3774
3775#ifndef __WIN32__
3776	if ((colorPtr->visualInfo.class != DirectColor)
3777		&& (colorPtr->visualInfo.class != TrueColor)) {
3778	    colorPtr->flags |= MAP_COLORS;
3779	}
3780#endif /* __WIN32__ */
3781    }
3782
3783    colorPtr->numColors = numColors;
3784    colorPtr->pixelMap = pixels;
3785
3786    /*
3787     * Set up quantization tables for dithering.
3788     */
3789    rMult = nGreen * nBlue;
3790    for (i = 0; i < 256; ++i) {
3791	r = (i * (nRed - 1) + 127) / 255;
3792	if (mono) {
3793	    fr = (double) colors[r].red / 65535.0;
3794	    if (colorPtr->id.gamma != 1.0 ) {
3795		fr = pow(fr, colorPtr->id.gamma);
3796	    }
3797	    colorPtr->colorQuant[0][i] = (int)(fr * 255.99);
3798	    colorPtr->redValues[i] = colors[r].pixel;
3799	} else {
3800	    g = (i * (nGreen - 1) + 127) / 255;
3801	    b = (i * (nBlue - 1) + 127) / 255;
3802	    if ((colorPtr->visualInfo.class == DirectColor)
3803		    || (colorPtr->visualInfo.class == TrueColor)) {
3804		colorPtr->redValues[i] = colors[r].pixel
3805		    & colorPtr->visualInfo.red_mask;
3806		colorPtr->greenValues[i] = colors[g].pixel
3807		    & colorPtr->visualInfo.green_mask;
3808		colorPtr->blueValues[i] = colors[b].pixel
3809		    & colorPtr->visualInfo.blue_mask;
3810	    } else {
3811		r *= rMult;
3812		g *= nBlue;
3813		colorPtr->redValues[i] = r;
3814		colorPtr->greenValues[i] = g;
3815		colorPtr->blueValues[i] = b;
3816	    }
3817	    fr = (double) colors[r].red / 65535.0;
3818	    fg = (double) colors[g].green / 65535.0;
3819	    fb = (double) colors[b].blue / 65535.0;
3820	    if (colorPtr->id.gamma != 1.0) {
3821		fr = pow(fr, colorPtr->id.gamma);
3822		fg = pow(fg, colorPtr->id.gamma);
3823		fb = pow(fb, colorPtr->id.gamma);
3824	    }
3825	    colorPtr->colorQuant[0][i] = (int)(fr * 255.99);
3826	    colorPtr->colorQuant[1][i] = (int)(fg * 255.99);
3827	    colorPtr->colorQuant[2][i] = (int)(fb * 255.99);
3828	}
3829    }
3830
3831    ckfree((char *) colors);
3832}
3833
3834/*
3835 *----------------------------------------------------------------------
3836 *
3837 * DisposeColorTable --
3838 *
3839 *
3840 * Results:
3841 *	None.
3842 *
3843 * Side effects:
3844 *	The colors in the argument color table are freed, as is the
3845 *	color table structure itself.  The color table is removed
3846 *	from the hash table which is used to locate color tables.
3847 *
3848 *----------------------------------------------------------------------
3849 */
3850
3851static void
3852DisposeColorTable(clientData)
3853    ClientData clientData;	/* Pointer to the ColorTable whose
3854				 * colors are to be released. */
3855{
3856    ColorTable *colorPtr;
3857    Tcl_HashEntry *entry;
3858
3859    colorPtr = (ColorTable *) clientData;
3860    if (colorPtr->pixelMap != NULL) {
3861	if (colorPtr->numColors > 0) {
3862	    XFreeColors(colorPtr->id.display, colorPtr->id.colormap,
3863		    colorPtr->pixelMap, colorPtr->numColors, 0);
3864	    Tk_FreeColormap(colorPtr->id.display, colorPtr->id.colormap);
3865	}
3866	ckfree((char *) colorPtr->pixelMap);
3867    }
3868
3869    entry = Tcl_FindHashEntry(&imgPhotoColorHash, (char *) &colorPtr->id);
3870    if (entry == NULL) {
3871	panic("DisposeColorTable couldn't find hash entry");
3872    }
3873    Tcl_DeleteHashEntry(entry);
3874
3875    ckfree((char *) colorPtr);
3876}
3877
3878/*
3879 *----------------------------------------------------------------------
3880 *
3881 * ReclaimColors --
3882 *
3883 *	This procedure is called to try to free up colors in the
3884 *	colormap used by a color table.  It looks for other color
3885 *	tables with the same colormap and with a zero live reference
3886 *	count, and frees their colors.  It only does so if there is
3887 *	the possibility of freeing up at least `numColors' colors.
3888 *
3889 * Results:
3890 *	The return value is TRUE if any colors were freed, FALSE
3891 *	otherwise.
3892 *
3893 * Side effects:
3894 *	ColorTables which are not currently in use may lose their
3895 *	color allocations.
3896 *
3897 *---------------------------------------------------------------------- */
3898
3899static int
3900ReclaimColors(id, numColors)
3901    ColorTableId *id;		/* Pointer to information identifying
3902				 * the color table which needs more colors. */
3903    int numColors;		/* Number of colors required. */
3904{
3905    Tcl_HashSearch srch;
3906    Tcl_HashEntry *entry;
3907    ColorTable *colorPtr;
3908    int nAvail;
3909
3910    /*
3911     * First scan through the color hash table to get an
3912     * upper bound on how many colors we might be able to free.
3913     */
3914
3915    nAvail = 0;
3916    entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch);
3917    while (entry != NULL) {
3918	colorPtr = (ColorTable *) Tcl_GetHashValue(entry);
3919	if ((colorPtr->id.display == id->display)
3920	    && (colorPtr->id.colormap == id->colormap)
3921	    && (colorPtr->liveRefCount == 0 )&& (colorPtr->numColors != 0)
3922	    && ((colorPtr->id.palette != id->palette)
3923		|| (colorPtr->id.gamma != id->gamma))) {
3924
3925	    /*
3926	     * We could take this guy's colors off him.
3927	     */
3928
3929	    nAvail += colorPtr->numColors;
3930	}
3931	entry = Tcl_NextHashEntry(&srch);
3932    }
3933
3934    /*
3935     * nAvail is an (over)estimate of the number of colors we could free.
3936     */
3937
3938    if (nAvail < numColors) {
3939	return 0;
3940    }
3941
3942    /*
3943     * Scan through a second time freeing colors.
3944     */
3945
3946    entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch);
3947    while ((entry != NULL) && (numColors > 0)) {
3948	colorPtr = (ColorTable *) Tcl_GetHashValue(entry);
3949	if ((colorPtr->id.display == id->display)
3950		&& (colorPtr->id.colormap == id->colormap)
3951		&& (colorPtr->liveRefCount == 0) && (colorPtr->numColors != 0)
3952		&& ((colorPtr->id.palette != id->palette)
3953		    || (colorPtr->id.gamma != id->gamma))) {
3954
3955	    /*
3956	     * Free the colors that this ColorTable has.
3957	     */
3958
3959	    XFreeColors(colorPtr->id.display, colorPtr->id.colormap,
3960		    colorPtr->pixelMap, colorPtr->numColors, 0);
3961	    numColors -= colorPtr->numColors;
3962	    colorPtr->numColors = 0;
3963	    ckfree((char *) colorPtr->pixelMap);
3964	    colorPtr->pixelMap = NULL;
3965	}
3966
3967	entry = Tcl_NextHashEntry(&srch);
3968    }
3969    return 1;			/* we freed some colors */
3970}
3971
3972/*
3973 *----------------------------------------------------------------------
3974 *
3975 * DisposeInstance --
3976 *
3977 *	This procedure is called to finally free up an instance
3978 *	of a photo image which is no longer required.
3979 *
3980 * Results:
3981 *	None.
3982 *
3983 * Side effects:
3984 *	The instance data structure and the resources it references
3985 *	are freed.
3986 *
3987 *----------------------------------------------------------------------
3988 */
3989
3990static void
3991DisposeInstance(clientData)
3992    ClientData clientData;	/* Pointer to the instance whose resources
3993				 * are to be released. */
3994{
3995    PhotoInstance *instancePtr = (PhotoInstance *) clientData;
3996    PhotoInstance *prevPtr;
3997
3998    if (instancePtr->pixels != None) {
3999	Tk_FreePixmap(instancePtr->display, instancePtr->pixels);
4000    }
4001    if (instancePtr->gc != None) {
4002	Tk_FreeGC(instancePtr->display, instancePtr->gc);
4003    }
4004    if (instancePtr->imagePtr != NULL) {
4005	XDestroyImage(instancePtr->imagePtr);
4006    }
4007    if (instancePtr->error != NULL) {
4008	ckfree((char *) instancePtr->error);
4009    }
4010    if (instancePtr->colorTablePtr != NULL) {
4011	FreeColorTable(instancePtr->colorTablePtr, 1);
4012    }
4013
4014    if (instancePtr->masterPtr->instancePtr == instancePtr) {
4015	instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
4016    } else {
4017	for (prevPtr = instancePtr->masterPtr->instancePtr;
4018		prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
4019	    /* Empty loop body */
4020	}
4021	prevPtr->nextPtr = instancePtr->nextPtr;
4022    }
4023    Tk_FreeColormap(instancePtr->display, instancePtr->colormap);
4024    ckfree((char *) instancePtr);
4025}
4026
4027/*
4028 *----------------------------------------------------------------------
4029 *
4030 * MatchFileFormat --
4031 *
4032 *	This procedure is called to find a photo image file format
4033 *	handler which can parse the image data in the given file.
4034 *	If a user-specified format string is provided, only handlers
4035 *	whose names match a prefix of the format string are tried.
4036 *
4037 * Results:
4038 *	A standard TCL return value.  If the return value is TCL_OK, a
4039 *	pointer to the image format record is returned in
4040 *	*imageFormatPtr, and the width and height of the image are
4041 *	returned in *widthPtr and *heightPtr.
4042 *
4043 * Side effects:
4044 *	None.
4045 *
4046 *----------------------------------------------------------------------
4047 */
4048
4049static int
4050MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr,
4051	widthPtr, heightPtr, oldformat)
4052    Tcl_Interp *interp;		/* Interpreter to use for reporting errors. */
4053    Tcl_Channel chan;		/* The image file, open for reading. */
4054    char *fileName;		/* The name of the image file. */
4055    Tcl_Obj *formatObj;		/* User-specified format string, or NULL. */
4056    Tk_PhotoImageFormat **imageFormatPtr;
4057				/* A pointer to the photo image format
4058				 * record is returned here. */
4059    int *widthPtr, *heightPtr;	/* The dimensions of the image are
4060				 * returned here. */
4061    int *oldformat;
4062{
4063    int matched;
4064    int useoldformat = 0;
4065    Tk_PhotoImageFormat *formatPtr;
4066    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
4067            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
4068    char *formatString = NULL;
4069
4070    if (formatObj) {
4071	formatString = Tcl_GetString(formatObj);
4072    }
4073
4074    /*
4075     * Scan through the table of file format handlers to find
4076     * one which can handle the image.
4077     */
4078
4079    matched = 0;
4080    for (formatPtr = tsdPtr->formatList; formatPtr != NULL;
4081	 formatPtr = formatPtr->nextPtr) {
4082	if (formatObj != NULL) {
4083	    if (strncasecmp(formatString,
4084		    formatPtr->name, strlen(formatPtr->name)) != 0) {
4085		continue;
4086	    }
4087	    matched = 1;
4088	    if (formatPtr->fileMatchProc == NULL) {
4089		Tcl_AppendResult(interp, "-file option isn't supported for ",
4090			formatString, " images", (char *) NULL);
4091		return TCL_ERROR;
4092	    }
4093	}
4094	if (formatPtr->fileMatchProc != NULL) {
4095	    (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
4096
4097	    if ((*formatPtr->fileMatchProc)(chan, fileName, formatObj,
4098		    widthPtr, heightPtr, interp)) {
4099		if (*widthPtr < 1) {
4100		    *widthPtr = 1;
4101		}
4102		if (*heightPtr < 1) {
4103		    *heightPtr = 1;
4104		}
4105		break;
4106	    }
4107	}
4108    }
4109    if (formatPtr == NULL) {
4110	useoldformat = 1;
4111	for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
4112		formatPtr = formatPtr->nextPtr) {
4113	    if (formatString != NULL) {
4114		if (strncasecmp(formatString,
4115			formatPtr->name, strlen(formatPtr->name)) != 0) {
4116		    continue;
4117		}
4118		matched = 1;
4119		if (formatPtr->fileMatchProc == NULL) {
4120		    Tcl_AppendResult(interp, "-file option isn't supported",
4121			    " for ", formatString, " images", (char *) NULL);
4122		    return TCL_ERROR;
4123		}
4124	    }
4125	    if (formatPtr->fileMatchProc != NULL) {
4126		(void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
4127		if ((*formatPtr->fileMatchProc)(chan, fileName, (Tcl_Obj *)
4128			formatString, widthPtr, heightPtr, interp)) {
4129		    if (*widthPtr < 1) {
4130			*widthPtr = 1;
4131		    }
4132		    if (*heightPtr < 1) {
4133			*heightPtr = 1;
4134		    }
4135		    break;
4136		}
4137	    }
4138	}
4139    }
4140
4141    if (formatPtr == NULL) {
4142	if ((formatObj != NULL) && !matched) {
4143	    Tcl_AppendResult(interp, "image file format \"",
4144		    formatString,
4145		    "\" is not supported", (char *) NULL);
4146	} else {
4147	    Tcl_AppendResult(interp,
4148		    "couldn't recognize data in image file \"",
4149		    fileName, "\"", (char *) NULL);
4150	}
4151	return TCL_ERROR;
4152    }
4153
4154    *imageFormatPtr = formatPtr;
4155    *oldformat = useoldformat;
4156    (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
4157    return TCL_OK;
4158}
4159
4160/*
4161 *----------------------------------------------------------------------
4162 *
4163 * MatchStringFormat --
4164 *
4165 *	This procedure is called to find a photo image file format
4166 *	handler which can parse the image data in the given string.
4167 *	If a user-specified format string is provided, only handlers
4168 *	whose names match a prefix of the format string are tried.
4169 *
4170 * Results:
4171 *	A standard TCL return value.  If the return value is TCL_OK, a
4172 *	pointer to the image format record is returned in
4173 *	*imageFormatPtr, and the width and height of the image are
4174 *	returned in *widthPtr and *heightPtr.
4175 *
4176 * Side effects:
4177 *	None.
4178 *
4179 *----------------------------------------------------------------------
4180 */
4181
4182static int
4183MatchStringFormat(interp, data, formatObj, imageFormatPtr,
4184	widthPtr, heightPtr, oldformat)
4185    Tcl_Interp *interp;		/* Interpreter to use for reporting errors. */
4186    Tcl_Obj *data;		/* Object containing the image data. */
4187    Tcl_Obj *formatObj;		/* User-specified format string, or NULL. */
4188    Tk_PhotoImageFormat **imageFormatPtr;
4189				/* A pointer to the photo image format
4190				 * record is returned here. */
4191    int *widthPtr, *heightPtr;	/* The dimensions of the image are
4192				 * returned here. */
4193    int *oldformat;		/* returns 1 if the old image API is used */
4194{
4195    int matched;
4196    int useoldformat = 0;
4197    Tk_PhotoImageFormat *formatPtr;
4198    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
4199            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
4200    char *formatString = NULL;
4201
4202    if (formatObj) {
4203	formatString = Tcl_GetString(formatObj);
4204    }
4205
4206    /*
4207     * Scan through the table of file format handlers to find
4208     * one which can handle the image.
4209     */
4210
4211    matched = 0;
4212    for (formatPtr = tsdPtr->formatList; formatPtr != NULL;
4213	    formatPtr = formatPtr->nextPtr) {
4214	if (formatObj != NULL) {
4215	    if (strncasecmp(formatString,
4216		    formatPtr->name, strlen(formatPtr->name)) != 0) {
4217		continue;
4218	    }
4219	    matched = 1;
4220	    if (formatPtr->stringMatchProc == NULL) {
4221		Tcl_AppendResult(interp, "-data option isn't supported for ",
4222			formatString, " images", (char *) NULL);
4223		return TCL_ERROR;
4224	    }
4225	}
4226	if ((formatPtr->stringMatchProc != NULL)
4227		&& (formatPtr->stringReadProc != NULL)
4228		&& (*formatPtr->stringMatchProc)(data, formatObj,
4229		widthPtr, heightPtr, interp)) {
4230	    break;
4231	}
4232    }
4233
4234    if (formatPtr == NULL) {
4235	useoldformat = 1;
4236	for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
4237		formatPtr = formatPtr->nextPtr) {
4238	    if (formatObj != NULL) {
4239		if (strncasecmp(formatString,
4240			formatPtr->name, strlen(formatPtr->name)) != 0) {
4241		    continue;
4242		}
4243		matched = 1;
4244		if (formatPtr->stringMatchProc == NULL) {
4245		    Tcl_AppendResult(interp, "-data option isn't supported",
4246			    " for ", formatString, " images", (char *) NULL);
4247		    return TCL_ERROR;
4248		}
4249	    }
4250	    if ((formatPtr->stringMatchProc != NULL)
4251		    && (formatPtr->stringReadProc != NULL)
4252		    && (*formatPtr->stringMatchProc)(
4253			    (Tcl_Obj *) Tcl_GetString(data),
4254			    (Tcl_Obj *) formatString,
4255			    widthPtr, heightPtr, interp)) {
4256		break;
4257	    }
4258	}
4259    }
4260    if (formatPtr == NULL) {
4261	if ((formatObj != NULL) && !matched) {
4262	    Tcl_AppendResult(interp, "image format \"", formatString,
4263		    "\" is not supported", (char *) NULL);
4264	} else {
4265	    Tcl_AppendResult(interp, "couldn't recognize image data",
4266		    (char *) NULL);
4267	}
4268	return TCL_ERROR;
4269    }
4270
4271    *imageFormatPtr = formatPtr;
4272    *oldformat = useoldformat;
4273    return TCL_OK;
4274}
4275
4276/*
4277 *----------------------------------------------------------------------
4278 *
4279 * Tk_FindPhoto --
4280 *
4281 *	This procedure is called to get an opaque handle (actually a
4282 *	PhotoMaster *) for a given image, which can be used in
4283 *	subsequent calls to Tk_PhotoPutBlock, etc.  The `name'
4284 *	parameter is the name of the image.
4285 *
4286 * Results:
4287 *	The handle for the photo image, or NULL if there is no
4288 *	photo image with the name given.
4289 *
4290 * Side effects:
4291 *	None.
4292 *
4293 *----------------------------------------------------------------------
4294 */
4295
4296Tk_PhotoHandle
4297Tk_FindPhoto(interp, imageName)
4298    Tcl_Interp *interp;		/* Interpreter (application) in which image
4299				 * exists. */
4300    CONST char *imageName;	/* Name of the desired photo image. */
4301{
4302    ClientData clientData;
4303    Tk_ImageType *typePtr;
4304
4305    clientData = Tk_GetImageMasterData(interp, imageName, &typePtr);
4306    if (typePtr != &tkPhotoImageType) {
4307	return NULL;
4308    }
4309    return (Tk_PhotoHandle) clientData;
4310}
4311
4312/*
4313 *----------------------------------------------------------------------
4314 *
4315 * Tk_PhotoPutBlock --
4316 *
4317 *	This procedure is called to put image data into a photo image.
4318 *
4319 * Results:
4320 *	None.
4321 *
4322 * Side effects:
4323 *	The image data is stored.  The image may be expanded.
4324 *	The Tk image code is informed that the image has changed.
4325 *
4326 *---------------------------------------------------------------------- */
4327
4328void
4329Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule)
4330    Tk_PhotoHandle handle;	/* Opaque handle for the photo image
4331				 * to be updated. */
4332    register Tk_PhotoImageBlock *blockPtr;
4333				/* Pointer to a structure describing the
4334				 * pixel data to be copied into the image. */
4335    int x, y;			/* Coordinates of the top-left pixel to
4336				 * be updated in the image. */
4337    int width, height;		/* Dimensions of the area of the image
4338				 * to be updated. */
4339    int compRule;		/* Compositing rule to use when processing
4340				 * transparent pixels. */
4341{
4342    register PhotoMaster *masterPtr;
4343    int xEnd, yEnd;
4344    int greenOffset, blueOffset, alphaOffset;
4345    int wLeft, hLeft;
4346    int wCopy, hCopy;
4347    unsigned char *srcPtr, *srcLinePtr;
4348    unsigned char *destPtr, *destLinePtr;
4349    int pitch;
4350    int sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO;
4351    XRectangle rect;
4352
4353    masterPtr = (PhotoMaster *) handle;
4354    compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO;
4355
4356    if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) {
4357	width = masterPtr->userWidth - x;
4358    }
4359    if ((masterPtr->userHeight != 0)
4360	    && ((y + height) > masterPtr->userHeight)) {
4361	height = masterPtr->userHeight - y;
4362    }
4363    if ((width <= 0) || (height <= 0)) {
4364	return;
4365    }
4366
4367    xEnd = x + width;
4368    yEnd = y + height;
4369    if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) {
4370	int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32);
4371	if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width),
4372		MAX(yEnd, masterPtr->height)) == TCL_ERROR) {
4373	    panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
4374	}
4375	if (sameSrc) {
4376	    blockPtr->pixelPtr = masterPtr->pix32;
4377	    blockPtr->pitch = masterPtr->width * 4;
4378	}
4379    }
4380
4381
4382    if ((y < masterPtr->ditherY) || ((y == masterPtr->ditherY)
4383	    && (x < masterPtr->ditherX))) {
4384	/*
4385	 * The dithering isn't correct past the start of this block.
4386	 */
4387	masterPtr->ditherX = x;
4388	masterPtr->ditherY = y;
4389    }
4390
4391    /*
4392     * If this image block could have different red, green and blue
4393     * components, mark it as a color image.
4394     */
4395
4396    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
4397    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
4398    alphaOffset = blockPtr->offset[3];
4399    if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) {
4400	alphaOffset = 0;
4401	sourceIsSimplePhoto = 1;
4402    } else {
4403	alphaOffset -= blockPtr->offset[0];
4404    }
4405    if ((greenOffset != 0) || (blueOffset != 0)) {
4406	masterPtr->flags |= COLOR_IMAGE;
4407    }
4408
4409    /*
4410     * Copy the data into our local 32-bit/pixel array.
4411     * If we can do it with a single memcpy, we do.
4412     */
4413
4414    destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
4415    pitch = masterPtr->width * 4;
4416
4417    /*
4418     * This test is probably too restrictive.  We should also be able to
4419     * do a memcpy if pixelSize == 3 and alphaOffset == 0.  Maybe other cases
4420     * too.
4421     */
4422    if ((blockPtr->pixelSize == 4)
4423	    && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3)
4424	    && (width <= blockPtr->width) && (height <= blockPtr->height)
4425	    && ((height == 1) || ((x == 0) && (width == masterPtr->width)
4426		&& (blockPtr->pitch == pitch)))
4427	    && (compRule == TK_PHOTO_COMPOSITE_SET)) {
4428	memcpy((VOID *) destLinePtr,
4429		(VOID *) (blockPtr->pixelPtr + blockPtr->offset[0]),
4430		(size_t) (height * width * 4));
4431    } else {
4432	int alpha;
4433	for (hLeft = height; hLeft > 0;) {
4434	    srcLinePtr = blockPtr->pixelPtr + blockPtr->offset[0];
4435	    hCopy = MIN(hLeft, blockPtr->height);
4436	    hLeft -= hCopy;
4437	    for (; hCopy > 0; --hCopy) {
4438		if ((blockPtr->pixelSize == 4) && (greenOffset == 1)
4439		    && (blueOffset == 2) && (alphaOffset == 3)
4440		    && (width <= blockPtr->width)
4441		    && (compRule == TK_PHOTO_COMPOSITE_SET)) {
4442		    memcpy((VOID *) destLinePtr, (VOID *) srcLinePtr,
4443			   (size_t) (width * 4));
4444		} else {
4445		    destPtr = destLinePtr;
4446		    for (wLeft = width; wLeft > 0;) {
4447			wCopy = MIN(wLeft, blockPtr->width);
4448			wLeft -= wCopy;
4449			srcPtr = srcLinePtr;
4450			for (; wCopy > 0; --wCopy) {
4451			    alpha = srcPtr[alphaOffset];
4452
4453			    /*
4454			     * In the easy case, we can just copy.
4455			     */
4456			    if (!alphaOffset || (alpha == 255)) {
4457				/* new solid part of the image */
4458				*destPtr++ = srcPtr[0];
4459				*destPtr++ = srcPtr[greenOffset];
4460				*destPtr++ = srcPtr[blueOffset];
4461				*destPtr++ = 255;
4462				srcPtr += blockPtr->pixelSize;
4463				continue;
4464			    }
4465
4466			    /*
4467			     * Combine according to the compositing rule.
4468			     */
4469			    switch (compRule) {
4470			    case TK_PHOTO_COMPOSITE_OVERLAY:
4471				if (!destPtr[3]) {
4472				    /*
4473				     * The destination is entirely
4474				     * blank, so set it to the source,
4475				     * just as if we used the SET
4476				     * compositing rule.
4477				     */
4478				case TK_PHOTO_COMPOSITE_SET:
4479				    *destPtr++ = srcPtr[0];
4480				    *destPtr++ = srcPtr[greenOffset];
4481				    *destPtr++ = srcPtr[blueOffset];
4482				    *destPtr++ = alpha;
4483				    break;
4484				}
4485
4486				if (alpha) {
4487				    int Alpha = destPtr[3];
4488
4489				    /*
4490				     * This implements the Porter-Duff
4491				     * Source-Over compositing rule.
4492				     */
4493
4494				    destPtr[0] = PD_SRC_OVER(srcPtr[0],alpha,destPtr[0],Alpha);
4495				    destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha,destPtr[1],Alpha);
4496				    destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset],alpha,destPtr[2],Alpha);
4497				    destPtr[3] = PD_SRC_OVER_ALPHA(alpha,Alpha);
4498				}
4499				/*
4500				 * else should be empty space
4501				 */
4502				destPtr += 4;
4503				break;
4504
4505			    default:
4506				panic("unknown compositing rule: %d", compRule);
4507			    }
4508			    srcPtr += blockPtr->pixelSize;
4509			}
4510		    }
4511		}
4512		srcLinePtr += blockPtr->pitch;
4513		destLinePtr += pitch;
4514	    }
4515	}
4516    }
4517
4518    /*
4519     * Add this new block to the region which specifies which data is valid.
4520     */
4521
4522    if (alphaOffset) {
4523	int x1, y1, end;
4524
4525	/*
4526	 * This block is grossly inefficient.  For each row in the image, it
4527	 * finds each continguous string of nontransparent pixels, then marks
4528	 * those areas as valid in the validRegion mask.  This makes drawing
4529	 * very efficient, because of the way we use X: we just say, here's
4530	 * your mask, and here's your data.  We need not worry about the
4531	 * current background color, etc.  But this costs us a lot on the
4532	 * image setup.  Still, image setup only happens once, whereas the
4533	 * drawing happens many times, so this might be the best way to go.
4534	 *
4535	 * An alternative might be to not set up this mask, and instead, at
4536	 * drawing time, for each transparent pixel, set its color to the
4537	 * color of the background behind that pixel.  This is what I suspect
4538	 * most of programs do.  However, they don't have to deal with the
4539	 * canvas, which could have many different background colors.
4540	 * Determining the correct bg color for a given pixel might be
4541	 * expensive.
4542	 */
4543
4544	if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) {
4545	    /*
4546	     * Don't need this when using the OVERLAY compositing rule,
4547	     * which always strictly increases the valid region.
4548	     */
4549	    TkRegion workRgn = TkCreateRegion();
4550
4551	    rect.x = x;
4552	    rect.y = y;
4553	    rect.width = width;
4554	    rect.height = height;
4555	    TkUnionRectWithRegion(&rect, workRgn, workRgn);
4556	    TkSubtractRegion(masterPtr->validRegion, workRgn,
4557		    masterPtr->validRegion);
4558	    TkDestroyRegion(workRgn);
4559	}
4560
4561	destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3;
4562	for (y1 = 0; y1 < height; y1++) {
4563	    x1 = 0;
4564	    destPtr = destLinePtr;
4565	    while (x1 < width) {
4566		/* search for first non-transparent pixel */
4567		while ((x1 < width) && !*destPtr) {
4568		    x1++;
4569		    destPtr += 4;
4570		}
4571		end = x1;
4572		/* search for first transparent pixel */
4573		while ((end < width) && *destPtr) {
4574		    end++;
4575		    destPtr += 4;
4576		}
4577		if (end > x1) {
4578		    rect.x = x + x1;
4579		    rect.y = y + y1;
4580		    rect.width = end - x1;
4581		    rect.height = 1;
4582		    TkUnionRectWithRegion(&rect, masterPtr->validRegion,
4583			    masterPtr->validRegion);
4584		}
4585		x1 = end;
4586	    }
4587	    destLinePtr += masterPtr->width * 4;
4588	}
4589    } else {
4590	rect.x = x;
4591	rect.y = y;
4592	rect.width = width;
4593	rect.height = height;
4594	TkUnionRectWithRegion(&rect, masterPtr->validRegion,
4595		masterPtr->validRegion);
4596    }
4597
4598    /*
4599     * Check if display code needs alpha blending...
4600     */
4601
4602    if (!sourceIsSimplePhoto && (width == 1) && (height == 1)) {
4603	/*
4604	 * Optimize the single pixel case if we can. This speeds up code that
4605	 * builds up large simple-alpha images by single pixels.  We don't
4606	 * negate COMPLEX_ALPHA in this case. [Bug 1409140]
4607	 */
4608	if (!(masterPtr->flags & COMPLEX_ALPHA)) {
4609	    unsigned char newAlpha;
4610
4611	    destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
4612	    newAlpha = destLinePtr[3];
4613
4614	    if (newAlpha && newAlpha != 255) {
4615		masterPtr->flags |= COMPLEX_ALPHA;
4616	    }
4617	}
4618    } else if ((alphaOffset != 0) || (masterPtr->flags & COMPLEX_ALPHA)) {
4619	/*
4620	 * Check for partial transparency if alpha pixels are specified, or
4621	 * rescan if we already knew such pixels existed.  To restrict this
4622	 * Toggle to only checking the changed pixels requires knowing where
4623	 * the alpha pixels are.
4624	 */
4625	ToggleComplexAlphaIfNeeded(masterPtr);
4626    }
4627
4628    /*
4629     * Update each instance.
4630     */
4631
4632    Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, x, y, width, height);
4633
4634    /*
4635     * Tell the core image code that this image has changed.
4636     */
4637
4638    Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width,
4639	    masterPtr->height);
4640}
4641
4642/*
4643 *----------------------------------------------------------------------
4644 *
4645 * Tk_PhotoPutZoomedBlock --
4646 *
4647 *	This procedure is called to put image data into a photo image,
4648 *	with possible subsampling and/or zooming of the pixels.
4649 *
4650 * Results:
4651 *	None.
4652 *
4653 * Side effects:
4654 *	The image data is stored.  The image may be expanded.
4655 *	The Tk image code is informed that the image has changed.
4656 *
4657 *----------------------------------------------------------------------
4658 */
4659
4660void
4661Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
4662	subsampleX, subsampleY, compRule)
4663    Tk_PhotoHandle handle;	/* Opaque handle for the photo image
4664				 * to be updated. */
4665    register Tk_PhotoImageBlock *blockPtr;
4666				/* Pointer to a structure describing the
4667				 * pixel data to be copied into the image. */
4668    int x, y;			/* Coordinates of the top-left pixel to
4669				 * be updated in the image. */
4670    int width, height;		/* Dimensions of the area of the image
4671				 * to be updated. */
4672    int zoomX, zoomY;		/* Zoom factors for the X and Y axes. */
4673    int subsampleX, subsampleY;	/* Subsampling factors for the X and Y axes. */
4674    int compRule;		/* Compositing rule to use when processing
4675				 * transparent pixels. */
4676{
4677    register PhotoMaster *masterPtr;
4678    int xEnd, yEnd;
4679    int greenOffset, blueOffset, alphaOffset;
4680    int wLeft, hLeft;
4681    int wCopy, hCopy;
4682    int blockWid, blockHt;
4683    unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr;
4684    unsigned char *destPtr, *destLinePtr;
4685    int pitch;
4686    int xRepeat, yRepeat;
4687    int blockXSkip, blockYSkip, sourceIsSimplePhoto;
4688    XRectangle rect;
4689
4690    if (zoomX==1 && zoomY==1 && subsampleX==1 && subsampleY==1) {
4691	Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule);
4692	return;
4693    }
4694
4695    sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO;
4696    compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO;
4697    masterPtr = (PhotoMaster *) handle;
4698
4699    if (zoomX <= 0 || zoomY <= 0) {
4700	return;
4701    }
4702    if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) {
4703	width = masterPtr->userWidth - x;
4704    }
4705    if ((masterPtr->userHeight != 0)
4706	    && ((y + height) > masterPtr->userHeight)) {
4707	height = masterPtr->userHeight - y;
4708    }
4709    if (width <= 0 || height <= 0) {
4710	return;
4711    }
4712
4713    xEnd = x + width;
4714    yEnd = y + height;
4715    if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) {
4716	int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32);
4717	if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width),
4718		MAX(yEnd, masterPtr->height)) == TCL_ERROR) {
4719	    panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
4720	}
4721	if (sameSrc) {
4722	    blockPtr->pixelPtr = masterPtr->pix32;
4723	    blockPtr->pitch = masterPtr->width * 4;
4724	}
4725    }
4726
4727    if ((y < masterPtr->ditherY) || ((y == masterPtr->ditherY)
4728	   && (x < masterPtr->ditherX))) {
4729	/*
4730	 * The dithering isn't correct past the start of this block.
4731	 */
4732
4733	masterPtr->ditherX = x;
4734	masterPtr->ditherY = y;
4735    }
4736
4737    /*
4738     * If this image block could have different red, green and blue
4739     * components, mark it as a color image.
4740     */
4741
4742    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
4743    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
4744    alphaOffset = blockPtr->offset[3];
4745    if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) {
4746	alphaOffset = 0;
4747	sourceIsSimplePhoto = 1;
4748    } else {
4749	alphaOffset -= blockPtr->offset[0];
4750    }
4751    if ((greenOffset != 0) || (blueOffset != 0)) {
4752	masterPtr->flags |= COLOR_IMAGE;
4753    }
4754
4755    /*
4756     * Work out what area the pixel data in the block expands to after
4757     * subsampling and zooming.
4758     */
4759
4760    blockXSkip = subsampleX * blockPtr->pixelSize;
4761    blockYSkip = subsampleY * blockPtr->pitch;
4762    if (subsampleX > 0) {
4763	blockWid = ((blockPtr->width + subsampleX - 1) / subsampleX) * zoomX;
4764    } else if (subsampleX == 0) {
4765	blockWid = width;
4766    } else {
4767	blockWid = ((blockPtr->width - subsampleX - 1) / -subsampleX) * zoomX;
4768    }
4769    if (subsampleY > 0) {
4770	blockHt = ((blockPtr->height + subsampleY - 1) / subsampleY) * zoomY;
4771    } else if (subsampleY == 0) {
4772	blockHt = height;
4773    } else {
4774	blockHt = ((blockPtr->height - subsampleY - 1) / -subsampleY) * zoomY;
4775    }
4776
4777    /*
4778     * Copy the data into our local 32-bit/pixel array.
4779     */
4780
4781    destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
4782    srcOrigPtr = blockPtr->pixelPtr + blockPtr->offset[0];
4783    if (subsampleX < 0) {
4784	srcOrigPtr += (blockPtr->width - 1) * blockPtr->pixelSize;
4785    }
4786    if (subsampleY < 0) {
4787	srcOrigPtr += (blockPtr->height - 1) * blockPtr->pitch;
4788    }
4789
4790    pitch = masterPtr->width * 4;
4791    for (hLeft = height; hLeft > 0; ) {
4792	hCopy = MIN(hLeft, blockHt);
4793	hLeft -= hCopy;
4794	yRepeat = zoomY;
4795	srcLinePtr = srcOrigPtr;
4796	for (; hCopy > 0; --hCopy) {
4797	    destPtr = destLinePtr;
4798	    for (wLeft = width; wLeft > 0;) {
4799		wCopy = MIN(wLeft, blockWid);
4800		wLeft -= wCopy;
4801		srcPtr = srcLinePtr;
4802		for (; wCopy > 0; wCopy -= zoomX) {
4803		    for (xRepeat = MIN(wCopy, zoomX); xRepeat > 0; xRepeat--) {
4804			int alpha = srcPtr[alphaOffset];
4805			/*
4806			 * Common case (solid pixels) first
4807			 */
4808			if (!alphaOffset || (alpha == 255)) {
4809			    *destPtr++ = srcPtr[0];
4810			    *destPtr++ = srcPtr[greenOffset];
4811			    *destPtr++ = srcPtr[blueOffset];
4812			    *destPtr++ = 255;
4813			    continue;
4814 			}
4815
4816			switch (compRule) {
4817			case TK_PHOTO_COMPOSITE_OVERLAY:
4818			    if (!destPtr[3]) {
4819				/*
4820				 * The destination is entirely blank,
4821				 * so set it to the source, just as if
4822				 * we used the SET compositing rule.
4823				 */
4824			    case TK_PHOTO_COMPOSITE_SET:
4825				*destPtr++ = srcPtr[0];
4826				*destPtr++ = srcPtr[greenOffset];
4827				*destPtr++ = srcPtr[blueOffset];
4828				*destPtr++ = alpha;
4829				break;
4830			    }
4831			    if (alpha) {
4832				int Alpha = destPtr[3];
4833				destPtr[0] = PD_SRC_OVER(srcPtr[0],alpha,destPtr[0],Alpha);
4834				destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha,destPtr[1],Alpha);
4835				destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset],alpha,destPtr[2],Alpha);
4836				destPtr[3] = PD_SRC_OVER_ALPHA(alpha,Alpha);
4837			    }
4838			    destPtr += 4;
4839			    break;
4840			default:
4841			    panic("unknown compositing rule: %d", compRule);
4842			}
4843		    }
4844		    srcPtr += blockXSkip;
4845		}
4846	    }
4847	    destLinePtr += pitch;
4848	    yRepeat--;
4849	    if (yRepeat <= 0) {
4850		srcLinePtr += blockYSkip;
4851		yRepeat = zoomY;
4852	    }
4853	}
4854    }
4855
4856    /*
4857     * Recompute the region of data for which we have valid pixels to plot.
4858     */
4859
4860    if (alphaOffset) {
4861	int x1, y1, end;
4862
4863	if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) {
4864	    /*
4865	     * Don't need this when using the OVERLAY compositing rule, which
4866	     * always strictly increases the valid region.
4867	     */
4868	    TkRegion workRgn = TkCreateRegion();
4869
4870	    rect.x = x;
4871	    rect.y = y;
4872	    rect.width = width;
4873	    rect.height = 1;
4874	    TkUnionRectWithRegion(&rect, workRgn, workRgn);
4875	    TkSubtractRegion(masterPtr->validRegion, workRgn,
4876		    masterPtr->validRegion);
4877	    TkDestroyRegion(workRgn);
4878	}
4879
4880	destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3;
4881	for (y1 = 0; y1 < height; y1++) {
4882	    x1 = 0;
4883	    destPtr = destLinePtr;
4884	    while (x1 < width) {
4885		/* search for first non-transparent pixel */
4886		while ((x1 < width) && !*destPtr) {
4887		    x1++;
4888		    destPtr += 4;
4889		}
4890		end = x1;
4891		/* search for first transparent pixel */
4892		while ((end < width) && *destPtr) {
4893		    end++;
4894		    destPtr += 4;
4895		}
4896		if (end > x1) {
4897		    rect.x = x + x1;
4898		    rect.y = y + y1;
4899		    rect.width = end - x1;
4900		    rect.height = 1;
4901		    TkUnionRectWithRegion(&rect, masterPtr->validRegion,
4902			    masterPtr->validRegion);
4903		}
4904		x1 = end;
4905	    }
4906	    destLinePtr += masterPtr->width * 4;
4907	}
4908    } else {
4909	rect.x = x;
4910	rect.y = y;
4911	rect.width = width;
4912	rect.height = height;
4913	TkUnionRectWithRegion(&rect, masterPtr->validRegion,
4914		masterPtr->validRegion);
4915    }
4916
4917    /*
4918     * Check if display code needs alpha blending...
4919     */
4920
4921    if (!sourceIsSimplePhoto && (width == 1) && (height == 1)) {
4922	/*
4923	 * Optimize the single pixel case if we can. This speeds up code that
4924	 * builds up large simple-alpha images by single pixels.  We don't
4925	 * negate COMPLEX_ALPHA in this case. [Bug 1409140]
4926	 */
4927	if (!(masterPtr->flags & COMPLEX_ALPHA)) {
4928	    unsigned char newAlpha;
4929
4930	    destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
4931	    newAlpha = destLinePtr[3];
4932
4933	    if (newAlpha && newAlpha != 255) {
4934		masterPtr->flags |= COMPLEX_ALPHA;
4935	    }
4936	}
4937    } else if ((alphaOffset != 0) || (masterPtr->flags & COMPLEX_ALPHA)) {
4938	/*
4939	 * Check for partial transparency if alpha pixels are specified, or
4940	 * rescan if we already knew such pixels existed.  To restrict this
4941	 * Toggle to only checking the changed pixels requires knowing where
4942	 * the alpha pixels are.
4943	 */
4944	ToggleComplexAlphaIfNeeded(masterPtr);
4945    }
4946
4947    /*
4948     * Update each instance.
4949     */
4950
4951    Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, x, y, width, height);
4952
4953    /*
4954     * Tell the core image code that this image has changed.
4955     */
4956
4957    Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width,
4958	    masterPtr->height);
4959}
4960
4961/*
4962 *----------------------------------------------------------------------
4963 *
4964 * Tk_DitherPhoto --
4965 *
4966 *	This procedure is called to update an area of each instance's
4967 *	pixmap by dithering the corresponding area of the image master.
4968 *
4969 * Results:
4970 *	None.
4971 *
4972 * Side effects:
4973 *	The pixmap of each instance of this image gets updated.
4974 *	The fields in *masterPtr indicating which area of the image
4975 *	is correctly dithered get updated.
4976 *
4977 *----------------------------------------------------------------------
4978 */
4979
4980void
4981Tk_DitherPhoto(photo, x, y, width, height)
4982    Tk_PhotoHandle photo;	/* Image master whose instances are
4983				 * to be updated. */
4984    int x, y;			/* Coordinates of the top-left pixel
4985				 * in the area to be dithered. */
4986    int width, height;		/* Dimensions of the area to be dithered. */
4987{
4988    PhotoMaster *masterPtr = (PhotoMaster *) photo;
4989    PhotoInstance *instancePtr;
4990
4991    if ((width <= 0) || (height <= 0)) {
4992	return;
4993    }
4994
4995    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
4996	    instancePtr = instancePtr->nextPtr) {
4997	DitherInstance(instancePtr, x, y, width, height);
4998    }
4999
5000    /*
5001     * Work out whether this block will be correctly dithered
5002     * and whether it will extend the correctly dithered region.
5003     */
5004
5005    if (((y < masterPtr->ditherY)
5006	    || ((y == masterPtr->ditherY) && (x <= masterPtr->ditherX)))
5007	    && ((y + height) > (masterPtr->ditherY))) {
5008
5009	/*
5010	 * This block starts inside (or immediately after) the correctly
5011	 * dithered region, so the first scan line at least will be right.
5012	 * Furthermore this block extends into scanline masterPtr->ditherY.
5013	 */
5014
5015	if ((x == 0) && (width == masterPtr->width)) {
5016	    /*
5017	     * We are doing the full width, therefore the dithering
5018	     * will be correct to the end.
5019	     */
5020
5021	    masterPtr->ditherX = 0;
5022	    masterPtr->ditherY = y + height;
5023	} else {
5024	    /*
5025	     * We are doing partial scanlines, therefore the
5026	     * correctly-dithered region will be extended by
5027	     * at most one scan line.
5028	     */
5029
5030	    if (x <= masterPtr->ditherX) {
5031		masterPtr->ditherX = x + width;
5032		if (masterPtr->ditherX >= masterPtr->width) {
5033		    masterPtr->ditherX = 0;
5034		    masterPtr->ditherY++;
5035		}
5036	    }
5037	}
5038    }
5039
5040}
5041
5042/*
5043 *----------------------------------------------------------------------
5044 *
5045 * DitherInstance --
5046 *
5047 *	This procedure is called to update an area of an instance's
5048 *	pixmap by dithering the corresponding area of the master.
5049 *
5050 * Results:
5051 *	None.
5052 *
5053 * Side effects:
5054 *	The instance's pixmap gets updated.
5055 *
5056 *----------------------------------------------------------------------
5057 */
5058
5059static void
5060DitherInstance(instancePtr, xStart, yStart, width, height)
5061    PhotoInstance *instancePtr;	/* The instance to be updated. */
5062    int xStart, yStart;		/* Coordinates of the top-left pixel in the
5063				 * block to be dithered. */
5064    int width, height;		/* Dimensions of the block to be dithered. */
5065{
5066    PhotoMaster *masterPtr;
5067    ColorTable *colorPtr;
5068    XImage *imagePtr;
5069    int nLines, bigEndian;
5070    int i, c, x, y;
5071    int xEnd, yEnd;
5072    int bitsPerPixel, bytesPerLine, lineLength;
5073    unsigned char *srcLinePtr, *srcPtr;
5074    schar *errLinePtr, *errPtr;
5075    unsigned char *destBytePtr, *dstLinePtr;
5076    pixel *destLongPtr;
5077    pixel firstBit, word, mask;
5078    int col[3];
5079    int doDithering = 1;
5080
5081    colorPtr = instancePtr->colorTablePtr;
5082    masterPtr = instancePtr->masterPtr;
5083
5084    /*
5085     * Turn dithering off in certain cases where it is not
5086     * needed (TrueColor, DirectColor with many colors).
5087     */
5088
5089    if ((colorPtr->visualInfo.class == DirectColor)
5090	    || (colorPtr->visualInfo.class == TrueColor)) {
5091	int nRed, nGreen, nBlue, result;
5092
5093	result = sscanf(colorPtr->id.palette, "%d/%d/%d", &nRed,
5094		&nGreen, &nBlue);
5095	if ((nRed >= 256)
5096		&& ((result == 1) || ((nGreen >= 256) && (nBlue >= 256)))) {
5097	    doDithering = 0;
5098	}
5099    }
5100
5101    /*
5102     * First work out how many lines to do at a time,
5103     * then how many bytes we'll need for pixel storage,
5104     * and allocate it.
5105     */
5106
5107    nLines = (MAX_PIXELS + width - 1) / width;
5108    if (nLines < 1) {
5109	nLines = 1;
5110    }
5111    if (nLines > height ) {
5112	nLines = height;
5113    }
5114
5115    imagePtr = instancePtr->imagePtr;
5116    if (imagePtr == NULL) {
5117	return;			/* we must be really tight on memory */
5118    }
5119    bitsPerPixel = imagePtr->bits_per_pixel;
5120    bytesPerLine = ((bitsPerPixel * width + 31) >> 3) & ~3;
5121    imagePtr->width = width;
5122    imagePtr->height = nLines;
5123    imagePtr->bytes_per_line = bytesPerLine;
5124    imagePtr->data = (char *) ckalloc((unsigned) (imagePtr->bytes_per_line * nLines));
5125    bigEndian = imagePtr->bitmap_bit_order == MSBFirst;
5126    firstBit = bigEndian? (1 << (imagePtr->bitmap_unit - 1)): 1;
5127
5128    lineLength = masterPtr->width * 3;
5129    srcLinePtr = masterPtr->pix32 + (yStart * masterPtr->width + xStart) * 4;
5130    errLinePtr = instancePtr->error + yStart * lineLength + xStart * 3;
5131    xEnd = xStart + width;
5132
5133    /*
5134     * Loop over the image, doing at most nLines lines before
5135     * updating the screen image.
5136     */
5137
5138    for (; height > 0; height -= nLines) {
5139	if (nLines > height) {
5140	    nLines = height;
5141	}
5142	dstLinePtr = (unsigned char *) imagePtr->data;
5143	yEnd = yStart + nLines;
5144	for (y = yStart; y < yEnd; ++y) {
5145	    srcPtr = srcLinePtr;
5146	    errPtr = errLinePtr;
5147	    destBytePtr = dstLinePtr;
5148	    destLongPtr = (pixel *) dstLinePtr;
5149	    if (colorPtr->flags & COLOR_WINDOW) {
5150		/*
5151		 * Color window.  We dither the three components
5152		 * independently, using Floyd-Steinberg dithering,
5153		 * which propagates errors from the quantization of
5154		 * pixels to the pixels below and to the right.
5155		 */
5156
5157		for (x = xStart; x < xEnd; ++x) {
5158		    if (doDithering) {
5159			for (i = 0; i < 3; ++i) {
5160			    /*
5161			     * Compute the error propagated into this pixel
5162			     * for this component.
5163			     * If e[x,y] is the array of quantization error
5164			     * values, we compute
5165			     *     7/16 * e[x-1,y] + 1/16 * e[x-1,y-1]
5166			     *   + 5/16 * e[x,y-1] + 3/16 * e[x+1,y-1]
5167			     * and round it to an integer.
5168			     *
5169			     * The expression ((c + 2056) >> 4) - 128
5170			     * computes round(c / 16), and works correctly on
5171			     * machines without a sign-extending right shift.
5172			     */
5173
5174			    c = (x > 0) ? errPtr[-3] * 7: 0;
5175			    if (y > 0) {
5176				if (x > 0) {
5177				    c += errPtr[-lineLength-3];
5178				}
5179				c += errPtr[-lineLength] * 5;
5180				if ((x + 1) < masterPtr->width) {
5181				    c += errPtr[-lineLength+3] * 3;
5182				}
5183			    }
5184
5185			    /*
5186			     * Add the propagated error to the value of this
5187			     * component, quantize it, and store the
5188			     * quantization error.
5189			     */
5190
5191			    c = ((c + 2056) >> 4) - 128 + *srcPtr++;
5192			    if (c < 0) {
5193				c = 0;
5194			    } else if (c > 255) {
5195				c = 255;
5196			    }
5197			    col[i] = colorPtr->colorQuant[i][c];
5198			    *errPtr++ = c - col[i];
5199			}
5200		    } else {
5201			/*
5202			 * Output is virtually continuous in this case,
5203			 * so don't bother dithering.
5204			 */
5205
5206			col[0] = *srcPtr++;
5207			col[1] = *srcPtr++;
5208			col[2] = *srcPtr++;
5209		    }
5210		    srcPtr++;
5211
5212		    /*
5213		     * Translate the quantized component values into
5214		     * an X pixel value, and store it in the image.
5215		     */
5216
5217		    i = colorPtr->redValues[col[0]]
5218			    + colorPtr->greenValues[col[1]]
5219			    + colorPtr->blueValues[col[2]];
5220		    if (colorPtr->flags & MAP_COLORS) {
5221			i = colorPtr->pixelMap[i];
5222		    }
5223		    switch (bitsPerPixel) {
5224			case NBBY:
5225			    *destBytePtr++ = i;
5226			    break;
5227#ifndef __WIN32__
5228/*
5229 * This case is not valid for Windows because the image format is different
5230 * from the pixel format in Win32.  Eventually we need to fix the image
5231 * code in Tk to use the Windows native image ordering.  This would speed
5232 * up the image code for all of the common sizes.
5233 */
5234
5235			case NBBY * sizeof(pixel):
5236			    *destLongPtr++ = i;
5237			    break;
5238#endif
5239			default:
5240			    XPutPixel(imagePtr, x - xStart, y - yStart,
5241				    (unsigned) i);
5242		    }
5243		}
5244
5245	    } else if (bitsPerPixel > 1) {
5246		/*
5247		 * Multibit monochrome window.  The operation here is similar
5248		 * to the color window case above, except that there is only
5249		 * one component.  If the master image is in color, use the
5250		 * luminance computed as
5251		 *	0.344 * red + 0.5 * green + 0.156 * blue.
5252		 */
5253
5254		for (x = xStart; x < xEnd; ++x) {
5255		    c = (x > 0) ? errPtr[-1] * 7: 0;
5256		    if (y > 0) {
5257			if (x > 0)  {
5258			    c += errPtr[-lineLength-1];
5259			}
5260			c += errPtr[-lineLength] * 5;
5261			if (x + 1 < masterPtr->width) {
5262			    c += errPtr[-lineLength+1] * 3;
5263			}
5264		    }
5265		    c = ((c + 2056) >> 4) - 128;
5266
5267		    if ((masterPtr->flags & COLOR_IMAGE) == 0) {
5268			c += srcPtr[0];
5269		    } else {
5270			c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16
5271					+ srcPtr[2] * 5 + 16) >> 5;
5272		    }
5273		    srcPtr += 4;
5274
5275		    if (c < 0) {
5276			c = 0;
5277		    } else if (c > 255) {
5278			c = 255;
5279		    }
5280		    i = colorPtr->colorQuant[0][c];
5281		    *errPtr++ = c - i;
5282		    i = colorPtr->redValues[i];
5283		    switch (bitsPerPixel) {
5284			case NBBY:
5285			    *destBytePtr++ = i;
5286			    break;
5287#ifndef __WIN32__
5288/*
5289 * This case is not valid for Windows because the image format is different
5290 * from the pixel format in Win32.  Eventually we need to fix the image
5291 * code in Tk to use the Windows native image ordering.  This would speed
5292 * up the image code for all of the common sizes.
5293 */
5294
5295			case NBBY * sizeof(pixel):
5296			    *destLongPtr++ = i;
5297			    break;
5298#endif
5299			default:
5300			    XPutPixel(imagePtr, x - xStart, y - yStart,
5301				    (unsigned) i);
5302		    }
5303		}
5304	    } else {
5305		/*
5306		 * 1-bit monochrome window.  This is similar to the
5307		 * multibit monochrome case above, except that the
5308		 * quantization is simpler (we only have black = 0
5309		 * and white = 255), and we produce an XY-Bitmap.
5310		 */
5311
5312		word = 0;
5313		mask = firstBit;
5314		for (x = xStart; x < xEnd; ++x) {
5315		    /*
5316		     * If we have accumulated a whole word, store it
5317		     * in the image and start a new word.
5318		     */
5319
5320		    if (mask == 0) {
5321			*destLongPtr++ = word;
5322			mask = firstBit;
5323			word = 0;
5324		    }
5325
5326		    c = (x > 0) ? errPtr[-1] * 7: 0;
5327		    if (y > 0) {
5328			if (x > 0) {
5329			    c += errPtr[-lineLength-1];
5330			}
5331			c += errPtr[-lineLength] * 5;
5332			if (x + 1 < masterPtr->width) {
5333			    c += errPtr[-lineLength+1] * 3;
5334			}
5335		    }
5336		    c = ((c + 2056) >> 4) - 128;
5337
5338		    if ((masterPtr->flags & COLOR_IMAGE) == 0) {
5339			c += srcPtr[0];
5340		    } else {
5341			c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16
5342					+ srcPtr[2] * 5 + 16) >> 5;
5343		    }
5344		    srcPtr += 4;
5345
5346		    if (c < 0) {
5347			c = 0;
5348		    } else if (c > 255) {
5349			c = 255;
5350		    }
5351		    if (c >= 128) {
5352			word |= mask;
5353			*errPtr++ = c - 255;
5354		    } else {
5355			*errPtr++ = c;
5356		    }
5357		    mask = bigEndian? (mask >> 1): (mask << 1);
5358		}
5359		*destLongPtr = word;
5360	    }
5361	    srcLinePtr += masterPtr->width * 4;
5362	    errLinePtr += lineLength;
5363	    dstLinePtr += bytesPerLine;
5364	}
5365
5366	/*
5367	 * Update the pixmap for this instance with the block of
5368	 * pixels that we have just computed.
5369	 */
5370
5371	TkPutImage(colorPtr->pixelMap, colorPtr->numColors,
5372		instancePtr->display, instancePtr->pixels,
5373		instancePtr->gc, imagePtr, 0, 0, xStart, yStart,
5374		(unsigned) width, (unsigned) nLines);
5375	yStart = yEnd;
5376
5377    }
5378
5379    ckfree(imagePtr->data);
5380    imagePtr->data = NULL;
5381}
5382
5383/*
5384 *----------------------------------------------------------------------
5385 *
5386 * Tk_PhotoBlank --
5387 *
5388 *	This procedure is called to clear an entire photo image.
5389 *
5390 * Results:
5391 *	None.
5392 *
5393 * Side effects:
5394 *	The valid region for the image is set to the null region.
5395 *	The generic image code is notified that the image has changed.
5396 *
5397 *----------------------------------------------------------------------
5398 */
5399
5400void
5401Tk_PhotoBlank(handle)
5402    Tk_PhotoHandle handle;	/* Handle for the image to be blanked. */
5403{
5404    PhotoMaster *masterPtr;
5405    PhotoInstance *instancePtr;
5406
5407    masterPtr = (PhotoMaster *) handle;
5408    masterPtr->ditherX = masterPtr->ditherY = 0;
5409    masterPtr->flags = 0;
5410
5411    /*
5412     * The image has valid data nowhere.
5413     */
5414
5415    if (masterPtr->validRegion != NULL) {
5416	TkDestroyRegion(masterPtr->validRegion);
5417    }
5418    masterPtr->validRegion = TkCreateRegion();
5419
5420    /*
5421     * Clear out the 32-bit pixel storage array.
5422     * Clear out the dithering error arrays for each instance.
5423     */
5424
5425    memset((VOID *) masterPtr->pix32, 0,
5426	    (size_t) (masterPtr->width * masterPtr->height * 4));
5427    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
5428	    instancePtr = instancePtr->nextPtr) {
5429	if (instancePtr->error) {
5430	    memset((VOID *) instancePtr->error, 0,
5431		    (size_t) (masterPtr->width * masterPtr->height
5432		    * 3 * sizeof(schar)));
5433	}
5434    }
5435
5436    /*
5437     * Tell the core image code that this image has changed.
5438     */
5439
5440    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
5441	    masterPtr->height, masterPtr->width, masterPtr->height);
5442}
5443
5444/*
5445 *----------------------------------------------------------------------
5446 *
5447 * Tk_PhotoExpand --
5448 *
5449 *	This procedure is called to request that a photo image be
5450 *	expanded if necessary to be at least `width' pixels wide and
5451 *	`height' pixels high.  If the user has declared a definite
5452 *	image size (using the -width and -height configuration
5453 *	options) then this call has no effect.
5454 *
5455 * Results:
5456 *	None.
5457 *
5458 * Side effects:
5459 *	The size of the photo image may change; if so the generic
5460 *	image code is informed.
5461 *
5462 *----------------------------------------------------------------------
5463 */
5464
5465void
5466Tk_PhotoExpand(handle, width, height)
5467    Tk_PhotoHandle handle;	/* Handle for the image to be expanded. */
5468    int width, height;		/* Desired minimum dimensions of the image. */
5469{
5470    PhotoMaster *masterPtr;
5471
5472    masterPtr = (PhotoMaster *) handle;
5473
5474    if (width <= masterPtr->width) {
5475	width = masterPtr->width;
5476    }
5477    if (height <= masterPtr->height) {
5478	height = masterPtr->height;
5479    }
5480    if ((width != masterPtr->width) || (height != masterPtr->height)) {
5481	if (ImgPhotoSetSize(masterPtr, MAX(width, masterPtr->width),
5482		MAX(height, masterPtr->height)) == TCL_ERROR) {
5483	    panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
5484	}
5485	Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width,
5486		masterPtr->height);
5487    }
5488}
5489
5490/*
5491 *----------------------------------------------------------------------
5492 *
5493 * Tk_PhotoGetSize --
5494 *
5495 *	This procedure is called to obtain the current size of a photo
5496 *	image.
5497 *
5498 * Results:
5499 *	The image's width and height are returned in *widthp
5500 *	and *heightp.
5501 *
5502 * Side effects:
5503 *	None.
5504 *
5505 *----------------------------------------------------------------------
5506 */
5507
5508void
5509Tk_PhotoGetSize(handle, widthPtr, heightPtr)
5510    Tk_PhotoHandle handle;	/* Handle for the image whose dimensions
5511				 * are requested. */
5512    int *widthPtr, *heightPtr;	/* The dimensions of the image are returned
5513				 * here. */
5514{
5515    PhotoMaster *masterPtr;
5516
5517    masterPtr = (PhotoMaster *) handle;
5518    *widthPtr = masterPtr->width;
5519    *heightPtr = masterPtr->height;
5520}
5521
5522/*
5523 *----------------------------------------------------------------------
5524 *
5525 * Tk_PhotoSetSize --
5526 *
5527 *	This procedure is called to set size of a photo image.
5528 *	This call is equivalent to using the -width and -height
5529 *	configuration options.
5530 *
5531 * Results:
5532 *	None.
5533 *
5534 * Side effects:
5535 *	The size of the image may change; if so the generic
5536 *	image code is informed.
5537 *
5538 *----------------------------------------------------------------------
5539 */
5540
5541void
5542Tk_PhotoSetSize(handle, width, height)
5543    Tk_PhotoHandle handle;	/* Handle for the image whose size is to
5544				 * be set. */
5545    int width, height;		/* New dimensions for the image. */
5546{
5547    PhotoMaster *masterPtr;
5548
5549    masterPtr = (PhotoMaster *) handle;
5550
5551    masterPtr->userWidth = width;
5552    masterPtr->userHeight = height;
5553    if (ImgPhotoSetSize(masterPtr, ((width > 0) ? width: masterPtr->width),
5554	    ((height > 0) ? height: masterPtr->height)) == TCL_ERROR) {
5555	panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
5556    }
5557    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
5558	    masterPtr->width, masterPtr->height);
5559}
5560
5561/*
5562 *----------------------------------------------------------------------
5563 *
5564 * TkGetPhotoValidRegion --
5565 *
5566 *	This procedure is called to get the part of the photo where
5567 *	there is valid data.  Or, conversely, the part of the photo
5568 *	which is transparent.
5569 *
5570 * Results:
5571 *	A TkRegion value that indicates the current area of the photo
5572 *	that is valid.  This value should not be used after any
5573 *	modification to the photo image.
5574 *
5575 * Side Effects:
5576 *	None.
5577 *
5578 *----------------------------------------------------------------------
5579 */
5580
5581TkRegion
5582TkPhotoGetValidRegion(handle)
5583    Tk_PhotoHandle handle; /* Handle for the image whose valid region
5584			    * is to obtained. */
5585{
5586    PhotoMaster *masterPtr;
5587
5588    masterPtr = (PhotoMaster *) handle;
5589    return masterPtr->validRegion;
5590}
5591
5592/*
5593 *----------------------------------------------------------------------
5594 *
5595 * ImgGetPhoto --
5596 *
5597 *	This procedure is called to obtain image data from a photo
5598 *	image.  This procedure fills in the Tk_PhotoImageBlock structure
5599 *	pointed to by `blockPtr' with details of the address and
5600 *	layout of the image data in memory.
5601 *
5602 * Results:
5603 *	A pointer to the allocated data which should be freed later.
5604 *	NULL if there is no need to free data because
5605 *	blockPtr->pixelPtr points directly to the image data.
5606 *
5607 * Side effects:
5608 *	None.
5609 *
5610 *----------------------------------------------------------------------
5611 */
5612
5613static char *
5614ImgGetPhoto(masterPtr, blockPtr, optPtr)
5615    PhotoMaster *masterPtr;	/* Handle for the photo image from which
5616				 * image data is desired. */
5617    Tk_PhotoImageBlock *blockPtr;
5618				/* Information about the address and layout
5619				 * of the image data is returned here. */
5620    struct SubcommandOptions *optPtr;
5621{
5622    unsigned char *pixelPtr;
5623    int x, y, greenOffset, blueOffset, alphaOffset;
5624
5625    Tk_PhotoGetImage((Tk_PhotoHandle) masterPtr, blockPtr);
5626    blockPtr->pixelPtr += optPtr->fromY * blockPtr->pitch
5627	    + optPtr->fromX * blockPtr->pixelSize;
5628    blockPtr->width = optPtr->fromX2 - optPtr->fromX;
5629    blockPtr->height = optPtr->fromY2 - optPtr->fromY;
5630
5631    if (!(masterPtr->flags & COLOR_IMAGE) &&
5632	    (!(optPtr->options & OPT_BACKGROUND)
5633	    || ((optPtr->background->red == optPtr->background->green)
5634	    && (optPtr->background->red == optPtr->background->blue)))) {
5635	blockPtr->offset[0] = blockPtr->offset[1] =
5636		blockPtr->offset[2];
5637    }
5638    alphaOffset = 0;
5639    for (y = 0; y < blockPtr->height; y++) {
5640	pixelPtr = blockPtr->pixelPtr + (y * blockPtr->pitch)
5641		+ blockPtr->pixelSize - 1;
5642	for (x = 0; x < blockPtr->width; x++) {
5643	    if (*pixelPtr != 255) {
5644		alphaOffset = 3;
5645		break;
5646	    }
5647	    pixelPtr += blockPtr->pixelSize;
5648	}
5649	if (alphaOffset) {
5650	    break;
5651	}
5652    }
5653    if (!alphaOffset) {
5654	blockPtr->pixelPtr--;
5655	blockPtr->offset[0]++;
5656	blockPtr->offset[1]++;
5657	blockPtr->offset[2]++;
5658    }
5659    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
5660    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
5661    if (((optPtr->options & OPT_BACKGROUND) && alphaOffset) ||
5662	    ((optPtr->options & OPT_GRAYSCALE) && (greenOffset || blueOffset))) {
5663	int newPixelSize,x,y;
5664	unsigned char *srcPtr, *destPtr;
5665	char *data;
5666
5667	newPixelSize =  (!(optPtr->options & OPT_BACKGROUND) && alphaOffset) ? 2 : 1;
5668	if ((greenOffset || blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) {
5669	    newPixelSize += 2;
5670	}
5671	data = ckalloc((unsigned int) (newPixelSize *
5672		blockPtr->width * blockPtr->height));
5673	srcPtr = blockPtr->pixelPtr + blockPtr->offset[0];
5674	destPtr = (unsigned char *) data;
5675	if (!greenOffset && !blueOffset) {
5676	    for (y = blockPtr->height; y > 0; y--) {
5677		for (x = blockPtr->width; x > 0; x--) {
5678		    *destPtr = *srcPtr;
5679		    srcPtr += blockPtr->pixelSize;
5680		    destPtr += newPixelSize;
5681		}
5682		srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize);
5683	    }
5684	} else if (optPtr->options & OPT_GRAYSCALE) {
5685	    for (y = blockPtr->height; y > 0; y--) {
5686		for (x = blockPtr->width; x > 0; x--) {
5687		    *destPtr = (unsigned char) ((srcPtr[0] * 11 + srcPtr[1] * 16
5688			    + srcPtr[2] * 5 + 16) >> 5);
5689		    srcPtr += blockPtr->pixelSize;
5690		    destPtr += newPixelSize;
5691		}
5692		srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize);
5693	    }
5694	} else {
5695	    for (y = blockPtr->height; y > 0; y--) {
5696		for (x = blockPtr->width; x > 0; x--) {
5697		    destPtr[0] = srcPtr[0];
5698		    destPtr[1] = srcPtr[1];
5699		    destPtr[2] = srcPtr[2];
5700		    srcPtr += blockPtr->pixelSize;
5701		    destPtr += newPixelSize;
5702		}
5703		srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize);
5704	    }
5705	}
5706	srcPtr = blockPtr->pixelPtr + alphaOffset;
5707	destPtr = (unsigned char *) data;
5708	if (!alphaOffset) {
5709	    /* nothing to be done */
5710	} else if (optPtr->options & OPT_BACKGROUND) {
5711	    if (newPixelSize > 2) {
5712	        int red = optPtr->background->red>>8;
5713	        int green = optPtr->background->green>>8;
5714	        int blue = optPtr->background->blue>>8;
5715		for (y = blockPtr->height; y > 0; y--) {
5716		    for (x = blockPtr->width; x > 0; x--) {
5717			destPtr[0] += (unsigned char) (((255 - *srcPtr) *
5718				(red-destPtr[0])) / 255);
5719			destPtr[1] += (unsigned char) (((255 - *srcPtr) *
5720				(green-destPtr[1])) / 255);
5721			destPtr[2] += (unsigned char) (((255 - *srcPtr) *
5722				(blue-destPtr[2])) / 255);
5723			srcPtr += blockPtr->pixelSize;
5724			destPtr += newPixelSize;
5725		    }
5726		    srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize);
5727		}
5728	    } else {
5729	 	int gray = (unsigned char) (((optPtr->background->red>>8) * 11
5730			    + (optPtr->background->green>>8) * 16
5731			    + (optPtr->background->blue>>8) * 5 + 16) >> 5);
5732		for (y = blockPtr->height; y > 0; y--) {
5733		    for (x = blockPtr->width; x > 0; x--) {
5734			destPtr[0] += ((255 - *srcPtr) *
5735				(gray-destPtr[0])) / 255;
5736			srcPtr += blockPtr->pixelSize;
5737			destPtr += newPixelSize;
5738		    }
5739		    srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize);
5740		}
5741	    }
5742	} else {
5743	    destPtr += newPixelSize-1;
5744	    for (y = blockPtr->height; y > 0; y--) {
5745		for (x = blockPtr->width; x > 0; x--) {
5746		    *destPtr = *srcPtr;
5747		    srcPtr += blockPtr->pixelSize;
5748		    destPtr += newPixelSize;
5749		}
5750		srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize);
5751	    }
5752	}
5753	blockPtr->pixelPtr = (unsigned char *) data;
5754	blockPtr->pixelSize = newPixelSize;
5755	blockPtr->pitch = newPixelSize * blockPtr->width;
5756	blockPtr->offset[0] = 0;
5757	if (newPixelSize>2) {
5758	    blockPtr->offset[1]= 1;
5759	    blockPtr->offset[2]= 2;
5760	} else {
5761	    blockPtr->offset[1]= 0;
5762	    blockPtr->offset[2]= 0;
5763	}
5764	return data;
5765    }
5766    return NULL;
5767}
5768
5769/*
5770 *----------------------------------------------------------------------
5771 *
5772 * ImgStringWrite --
5773 *
5774 *	Default string write function. The data is formatted in
5775 *	the default format as accepted by the "<img> put" command.
5776 *
5777 * Results:
5778 *	A standard Tcl result.
5779 *
5780 * Side effects:
5781 *	See the user documentation.
5782 *
5783 *----------------------------------------------------------------------
5784 */
5785
5786static int
5787ImgStringWrite(interp, formatString, blockPtr)
5788    Tcl_Interp *interp;
5789    Tcl_Obj *formatString;
5790    Tk_PhotoImageBlock *blockPtr;
5791{
5792    int row,col;
5793    char *line, *linePtr;
5794    unsigned char *pixelPtr;
5795    int greenOffset, blueOffset;
5796    Tcl_DString data;
5797
5798    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
5799    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
5800
5801    Tcl_DStringInit(&data);
5802    if ((blockPtr->width > 0) && (blockPtr->height > 0)) {
5803	line = (char *) ckalloc((unsigned int) ((8 * blockPtr->width) + 2));
5804	for (row=0; row<blockPtr->height; row++) {
5805	    pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] +
5806		    row * blockPtr->pitch;
5807	    linePtr = line;
5808	    for (col=0; col<blockPtr->width; col++) {
5809		sprintf(linePtr, " #%02x%02x%02x", *pixelPtr,
5810			pixelPtr[greenOffset], pixelPtr[blueOffset]);
5811		pixelPtr += blockPtr->pixelSize;
5812		linePtr += 8;
5813	    }
5814	    Tcl_DStringAppendElement(&data, line+1);
5815	}
5816	ckfree (line);
5817    }
5818    Tcl_DStringResult(interp, &data);
5819    return TCL_OK;
5820}
5821
5822/*
5823 *----------------------------------------------------------------------
5824 *
5825 * Tk_PhotoGetImage --
5826 *
5827 *	This procedure is called to obtain image data from a photo
5828 *	image.  This procedure fills in the Tk_PhotoImageBlock structure
5829 *	pointed to by `blockPtr' with details of the address and
5830 *	layout of the image data in memory.
5831 *
5832 * Results:
5833 *	TRUE (1) indicating that image data is available,
5834 *	for backwards compatibility with the old photo widget.
5835 *
5836 * Side effects:
5837 *	None.
5838 *
5839 *----------------------------------------------------------------------
5840 */
5841
5842int
5843Tk_PhotoGetImage(handle, blockPtr)
5844    Tk_PhotoHandle handle;	/* Handle for the photo image from which
5845				 * image data is desired. */
5846    Tk_PhotoImageBlock *blockPtr;
5847				/* Information about the address and layout
5848				 * of the image data is returned here. */
5849{
5850    PhotoMaster *masterPtr;
5851
5852    masterPtr = (PhotoMaster *) handle;
5853    blockPtr->pixelPtr = masterPtr->pix32;
5854    blockPtr->width = masterPtr->width;
5855    blockPtr->height = masterPtr->height;
5856    blockPtr->pitch = masterPtr->width * 4;
5857    blockPtr->pixelSize = 4;
5858    blockPtr->offset[0] = 0;
5859    blockPtr->offset[1] = 1;
5860    blockPtr->offset[2] = 2;
5861    blockPtr->offset[3] = 3;
5862    return 1;
5863}
5864
5865/*
5866 *----------------------------------------------------------------------
5867 *
5868 * PhotoOptionFind --
5869 *
5870 *	Finds a specific Photo option.
5871 *
5872 * Results:
5873 *	None.
5874 *
5875 * Side effects:
5876 *	After commands are removed.
5877 *
5878 *----------------------------------------------------------------------
5879 */
5880
5881typedef struct OptionAssocData {
5882    struct OptionAssocData *nextPtr;	/* pointer to next OptionAssocData */
5883    Tcl_ObjCmdProc *command;		/* command associated with this
5884					 * option */
5885    char name[1];			/* name of option (remaining chars) */
5886} OptionAssocData;
5887
5888static Tcl_ObjCmdProc *
5889PhotoOptionFind(interp, obj)
5890    Tcl_Interp *interp;		/* Interpreter that is being deleted. */
5891    Tcl_Obj *obj;			/* Name of option to be found. */
5892{
5893    int length;
5894    char *name = Tcl_GetStringFromObj(obj, &length);
5895    OptionAssocData *list;
5896    char *prevname = NULL;
5897    Tcl_ObjCmdProc *proc = (Tcl_ObjCmdProc *) NULL;
5898
5899    list = (OptionAssocData *) Tcl_GetAssocData(interp, "photoOption",
5900	    (Tcl_InterpDeleteProc **) NULL);
5901    while (list != (OptionAssocData *) NULL) {
5902	if (strncmp(name, list->name, (unsigned) length) == 0) {
5903	    if (proc != (Tcl_ObjCmdProc *) NULL) {
5904		Tcl_ResetResult(interp);
5905		Tcl_AppendResult(interp, "ambiguous option \"", name,
5906			"\": must be ", prevname, (char *) NULL);
5907		while (list->nextPtr != (OptionAssocData *) NULL) {
5908		    Tcl_AppendResult(interp, prevname, ", ",(char *) NULL);
5909		    list = list->nextPtr;
5910		    prevname = list->name;
5911		}
5912		Tcl_AppendResult(interp, ", or", prevname, (char *) NULL);
5913		return (Tcl_ObjCmdProc *) NULL;
5914	    }
5915	    proc = list->command;
5916	    prevname = list->name;
5917	}
5918	list = list->nextPtr;
5919    }
5920    if (proc != (Tcl_ObjCmdProc *) NULL) {
5921	Tcl_ResetResult(interp);
5922    }
5923    return proc;
5924}
5925
5926/*
5927 *----------------------------------------------------------------------
5928 *
5929 * PhotoOptionCleanupProc --
5930 *
5931 *	This procedure is invoked whenever an interpreter is deleted
5932 *	to cleanup the AssocData for "photoVisitor".
5933 *
5934 * Results:
5935 *	None.
5936 *
5937 * Side effects:
5938 *	Photo Visitor options are removed.
5939 *
5940 *----------------------------------------------------------------------
5941 */
5942
5943static void
5944PhotoOptionCleanupProc(clientData, interp)
5945    ClientData clientData;	/* Points to "photoVisitor" AssocData
5946				 * for the interpreter. */
5947    Tcl_Interp *interp;		/* Interpreter that is being deleted. */
5948{
5949    OptionAssocData *list = (OptionAssocData *) clientData;
5950    OptionAssocData *ptr;
5951
5952    while (list != NULL) {
5953	list = (ptr = list)->nextPtr;
5954	ckfree((char *) ptr);
5955    }
5956}
5957
5958/*
5959 *--------------------------------------------------------------
5960 *
5961 * Tk_CreatePhotoOption --
5962 *
5963 *	This procedure may be invoked to add a new kind of photo
5964 *	option to the core photo command supported by Tk.
5965 *
5966 * Results:
5967 *	None.
5968 *
5969 * Side effects:
5970 *	From now on, the new option will be useable by the
5971 *	photo command.
5972 *
5973 *--------------------------------------------------------------
5974 */
5975
5976void
5977Tk_CreatePhotoOption(interp, name, proc)
5978    Tcl_Interp *interp;			/* interpreter */
5979    CONST char *name;			/* option name */
5980    Tcl_ObjCmdProc *proc;		/* proc to execute command */
5981{
5982    OptionAssocData *typePtr2, *prevPtr, *ptr;
5983    OptionAssocData *list;
5984
5985    list = (OptionAssocData *) Tcl_GetAssocData(interp, "photoOption",
5986	    (Tcl_InterpDeleteProc **) NULL);
5987
5988    /*
5989     * If there's already a photo option with the given name, remove it.
5990     */
5991
5992    for (typePtr2 = list, prevPtr = NULL; typePtr2 != NULL;
5993	    prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
5994	if (strcmp(typePtr2->name, name) == 0) {
5995	    if (prevPtr == NULL) {
5996		list = typePtr2->nextPtr;
5997	    } else {
5998		prevPtr->nextPtr = typePtr2->nextPtr;
5999	    }
6000	    ckfree((char *) typePtr2);
6001	    break;
6002	}
6003    }
6004    ptr = (OptionAssocData *) ckalloc(sizeof(OptionAssocData) + strlen(name));
6005    strcpy(&(ptr->name[0]), name);
6006    ptr->command = proc;
6007    ptr->nextPtr = list;
6008    Tcl_SetAssocData(interp, "photoOption", PhotoOptionCleanupProc,
6009		(ClientData) ptr);
6010}
6011
6012/*
6013 *--------------------------------------------------------------
6014 *
6015 * TkPostscriptPhoto --
6016 *
6017 *	This procedure is called to output the contents of a
6018 *	photo image in Postscript by calling the Tk_PostscriptPhoto
6019 *	function.
6020 *
6021 * Results:
6022 *	Returns a standard Tcl return value.
6023 *
6024 * Side effects:
6025 *	None.
6026 *
6027 *--------------------------------------------------------------
6028 */
6029static int
6030ImgPhotoPostscript(clientData, interp, tkwin, psInfo,
6031        x, y, width, height, prepass)
6032     ClientData clientData;	/* Handle for the photo image */
6033    Tcl_Interp *interp;		/* Interpreter */
6034    Tk_Window tkwin;		/* (unused) */
6035    Tk_PostscriptInfo psInfo;	/* postscript info */
6036    int x, y;			/* First pixel to output */
6037    int width, height;		/* Width and height of area */
6038    int prepass;		/* (unused) */
6039{
6040    Tk_PhotoImageBlock block;
6041
6042    Tk_PhotoGetImage((Tk_PhotoHandle) clientData, &block);
6043    block.pixelPtr += y * block.pitch + x * block.pixelSize;
6044
6045    return Tk_PostscriptPhoto(interp, &block, psInfo, width, height);
6046}
6047
6048/*
6049 *----------------------------------------------------------------------
6050 *
6051 * Tk_PhotoPutBlock_NoComposite, Tk_PhotoPutZoomedBlock_NoComposite --
6052 *
6053 * These backward-compatability functions just exist to fill slots in
6054 * stubs table.  For the behaviour of *_NoComposite, refer to the
6055 * corresponding function without the extra suffix.
6056 *
6057 *----------------------------------------------------------------------
6058 */
6059void
6060Tk_PhotoPutBlock_NoComposite(handle, blockPtr, x, y, width, height)
6061     Tk_PhotoHandle handle;
6062     Tk_PhotoImageBlock *blockPtr;
6063     int x, y, width, height;
6064{
6065    Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height,
6066	    TK_PHOTO_COMPOSITE_OVERLAY);
6067}
6068
6069void
6070Tk_PhotoPutZoomedBlock_NoComposite(handle, blockPtr, x, y, width, height,
6071				   zoomX, zoomY, subsampleX, subsampleY)
6072     Tk_PhotoHandle handle;
6073     Tk_PhotoImageBlock *blockPtr;
6074     int x, y, width, height, zoomX, zoomY, subsampleX, subsampleY;
6075{
6076    Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height,
6077	    zoomX, zoomY, subsampleX, subsampleY, TK_PHOTO_COMPOSITE_OVERLAY);
6078}
6079