summaryrefslogtreecommitdiffstats
path: root/tkimg/xpm/xpm.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2017-01-03 21:51:01 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2017-01-03 21:51:01 (GMT)
commita780057cc1b51dd3a557549c3cf2431f09136c0d (patch)
tree717f78052c55596449b27743171d7e170c4d39a0 /tkimg/xpm/xpm.c
parent7749430b9352c1eaf5dca7d8a89a6d35f565ef24 (diff)
downloadblt-a780057cc1b51dd3a557549c3cf2431f09136c0d.zip
blt-a780057cc1b51dd3a557549c3cf2431f09136c0d.tar.gz
blt-a780057cc1b51dd3a557549c3cf2431f09136c0d.tar.bz2
upgrade tkimg to 1.4.6
Diffstat (limited to 'tkimg/xpm/xpm.c')
-rw-r--r--tkimg/xpm/xpm.c1032
1 files changed, 0 insertions, 1032 deletions
diff --git a/tkimg/xpm/xpm.c b/tkimg/xpm/xpm.c
deleted file mode 100644
index 3c5f030..0000000
--- a/tkimg/xpm/xpm.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * xpm.c --
- *
- * A photo image file handler for XPM files.
- *
- * Written by:
- * Jan Nijtmans
- * email: nijtmans@users.sourceforge.net
- * url: http://purl.oclc.org/net/nijtmans/
- *
- * (with some code stolen from the XPM image type and the GIF handler)
- *
- * <mweilguni@sime.com> Mario Weilguni
- * Jan 1997:
- * - fixed a bug when reading images with invalid color tables
- * (if a pixelchar is not in the colormap)
- * - added FileWriteXPM, StringWriteXPM and WriteXPM.
- * - modified FileReadXPM, ReadXPM and added StringReadXPM
- * This makes the XPM reader complete :-)
- *
- * <paul@poSoft.de> Paul Obermeier
- * Jan 2001:
- * - Bugfix in CommonWriteXPM: const char *fileName was overwritten.
- * - Bugfix in CommonWriteXPM: If used with "-from" option, dumped core.
- * - Improve in CommonWriteXPM: Greater channel buffersize for better
- * Win98 (i.e. FAT32) performance.
- * - Improve in ChnRead: Better performance by using ReadBuffer.
- *
- * $Id: xpm.c,v 1.1.1.1 2016/01/25 21:20:47 joye Exp $
- */
-
-/*
- * Generic initialization code, parameterized via CPACKAGE and PACKAGE.
- */
-
-#include "init.c"
-
-#if defined(__WIN32__) && !defined(__GNUC__)
-#define strncasecmp strnicmp
-#endif
-
-#ifndef MAC_TCL
-#include <sys/types.h>
-#endif
-
-/* constants used only in this file */
-
-#define XPM_MONO 1
-#define XPM_GRAY_4 2
-#define XPM_GRAY 3
-#define XPM_COLOR 4
-#define XPM_SYMBOLIC 5
-#define XPM_UNKNOWN 6
-
-#define MAX_BUFFER 4096
-
-/*
- * Prototypes for local procedures defined in this file:
- */
-
-static int CommonRead(Tcl_Interp *interp, tkimg_MFile *handle,
- Tcl_Obj *format, Tk_PhotoHandle imageHandle,
- int destX, int destY, int width, int height,
- int srcX, int srcY);
-static int CommonWrite(Tcl_Interp *interp, const char *fileName,
- Tcl_DString *dataPtr, Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr);
-
-static int ReadXPMFileHeader(tkimg_MFile *handle,
- int *widthPtr, int *heightPtr, int *numColors, int *byteSize);
-static char *GetType(char *colorDefn, int *type_ret);
-static char *GetColor(char *colorDefn, char *colorName, int *type_ret);
-static char *Gets(tkimg_MFile *handle, char *buffer, int size);
-
-/*
- *----------------------------------------------------------------------
- * Gets
- *
- * Allows other routines to get their data from channels, files as well
- * as Tcl_DStrings.
- *
- * Results:
- * same as fgets: NULL pointer on any error, otherwise
- * it returns buffer
- *
- * Side effects:
- * The access position of the file changes OR
- * The access pointer dataPtr->p is changed
- *
- *----------------------------------------------------------------------
- */
-
-static char *
-Gets(handle, buffer, size)
- tkimg_MFile *handle;
- char *buffer;
- int size;
-{
- char *p;
-
- /* read data from tkimg_MFile */
- p = buffer;
- while ((tkimg_Read(handle, p, 1) == 1)) {
- if (--size <= 0) {
- *p = 0; return buffer;
- }
- if (*p++ == '\n') {
- *p = 0;
- return buffer;
- }
- }
- *p = 0;
- return (p != buffer) ? buffer :(char *) NULL;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ObjMatch --
- *
- * This procedure is invoked by the photo image type to see if
- * a datastring contains image data in XPM format.
- *
- * Results:
- * The return value is >0 if the first characters in data look
- * like XPM data, and 0 otherwise.
- *
- * Side effects:
- * none
- *
- *----------------------------------------------------------------------
- */
-static int ObjMatch(
- Tcl_Obj *data, /* The data supplied by the image */
- Tcl_Obj *format, /* User-specified format object, or NULL. */
- int *widthPtr, /* The dimensions of the image are */
- int *heightPtr, /* returned here if the file is a valid
- * raw XPM file. */
- Tcl_Interp *interp
-) {
- int numColors, byteSize;
- tkimg_MFile handle;
-
- handle.data = (char *)tkimg_GetStringFromObj(data, &handle.length);
- handle.state = IMG_STRING;
-
- return ReadXPMFileHeader(&handle, widthPtr, heightPtr, &numColors, &byteSize);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ChnMatch --
- *
- * This procedure is invoked by the photo image type to see if
- * a file contains image data in XPM format.
- *
- * Results:
- * The return value is >0 if the first characters in channel "chan"
- * look like XPM data, and 0 otherwise.
- *
- * Side effects:
- * The access position in chan may change.
- *
- *----------------------------------------------------------------------
- */
-
-static int ChnMatch(
- Tcl_Channel chan, /* The image channel, open for reading. */
- const char *fileName, /* The name of the image file. */
- Tcl_Obj *format, /* User-specified format object, or NULL. */
- int *widthPtr, /* The dimensions of the image are */
- int *heightPtr, /* returned here if the file is a valid
- * raw XPM file. */
- Tcl_Interp *interp
-) {
- int numColors, byteSize;
- tkimg_MFile handle;
-
- handle.data = (char *) chan;
- handle.state = IMG_CHAN;
-
- return ReadXPMFileHeader(&handle, widthPtr, heightPtr, &numColors, &byteSize);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CommonRead --
- *
- * This procedure is called by the photo image type to read
- * XPM format data from a file or string and write it into a
- * given photo image.
- *
- * Results:
- * A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
- *
- * Side effects:
- * The access position in file f is changed (if read from file)
- * and new data is added to the image given by imageHandle.
- *
- *----------------------------------------------------------------------
- */
-static int
-CommonRead(interp, handle, format, imageHandle, destX, destY,
- width, height, srcX, srcY)
- Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
- tkimg_MFile *handle; /* The image channel, open for reading. */
- Tcl_Obj *format; /* User-specified format object, or NULL. */
- Tk_PhotoHandle imageHandle; /* The photo image to write into. */
- int destX, destY; /* Coordinates of top-left pixel in
- * photo image to be written to. */
- int width, height; /* Dimensions of block of photo image to
- * be written to. */
- int srcX, srcY; /* Coordinates of top-left pixel to be used
- * in image being read. */
-{
- int fileWidth = 0, fileHeight = 0, numColors = 0, byteSize = 0;
- int h, type;
- int nchan, matte = 1;
- unsigned char *pixelPtr;
- Tk_PhotoImageBlock block;
- Tcl_HashTable colorTable;
- Tk_Window tkwin = Tk_MainWindow(interp);
- Display *display = Tk_Display(tkwin);
- Colormap colormap = Tk_Colormap(tkwin);
- int depth = Tk_Depth(tkwin);
- char *p;
- char buffer[MAX_BUFFER];
- int i, isMono;
- int color1;
- unsigned int data;
- Tcl_HashEntry *hPtr;
- int result = TCL_OK;
-
- Tcl_InitHashTable(&colorTable, TCL_ONE_WORD_KEYS);
-
- switch ((Tk_Visual(tkwin))->class) {
- case StaticGray:
- case GrayScale:
- isMono = 1;
- break;
- default:
- isMono = 0;
- }
-
- type = ReadXPMFileHeader(handle, &fileWidth, &fileHeight, &numColors, &byteSize);
- if (type == 0) {
- Tcl_AppendResult(interp, "couldn't read raw XPM header", NULL);
- return TCL_ERROR;
- }
- if ((fileWidth <= 0) || (fileHeight <= 0)) {
- Tcl_AppendResult(interp, "XPM image file has dimension(s) <= 0",
- (char *) NULL);
- return TCL_ERROR;
- }
- if ((byteSize < 1) || (byteSize > 4)) {
- Tcl_AppendResult(interp, "XPM image file has invalid byte size ",
- "(should be 1, 2, 3 or 4)", (char *) NULL);
- return TCL_ERROR;
- }
-
- if ((srcX + width) > fileWidth) {
- width = fileWidth - srcX;
- }
- if ((srcY + height) > fileHeight) {
- height = fileHeight - srcY;
- }
- if ((width <= 0) || (height <= 0)
- || (srcX >= fileWidth) || (srcY >= fileHeight)) {
- return TCL_OK;
- }
-
- for (i=0; i<numColors; i++) {
- char * colorDefn; /* the color definition line */
- char * colorName; /* temp place to hold the color name
- * defined for one type of visual */
- char * useName; /* the color name used for this
- * color. If there are many names
- * defined, choose the name that is
- * "best" for the target visual
- */
- XColor color;
- int found;
-
- p = Gets(handle, buffer,MAX_BUFFER);
- while (((p = strchr(p,'\"')) == NULL)) {
- p = Gets(handle, buffer,MAX_BUFFER);
- if (p == NULL) {
- return TCL_ERROR;
- }
- p = buffer;
- }
- colorDefn = p + byteSize + 1;
- colorName = (char*)ckalloc(strlen(colorDefn)+1);
- useName = (char*)ckalloc(strlen(colorDefn)+1);
- found = 0;
- color1 = 0;
- data = 0;
-
- while (colorDefn && *colorDefn) {
- int type;
-
- if ((colorDefn=GetColor(colorDefn, colorName, &type)) == NULL) {
- break;
- }
- if (colorName[0] == '\0') {
- continue;
- }
-
- switch (type) {
- case XPM_MONO:
- if (isMono && depth == 1) {
- strcpy(useName, colorName);
- found = 1; goto gotcolor;
- }
- break;
- case XPM_GRAY_4:
- if (isMono && depth == 4) {
- strcpy(useName, colorName);
- found = 1; goto gotcolor;
- }
- break;
- case XPM_GRAY:
- if (isMono && depth > 4) {
- strcpy(useName, colorName);
- found = 1; goto gotcolor;
- }
- break;
- case XPM_COLOR:
- if (!isMono) {
- strcpy(useName, colorName);
- found = 1; goto gotcolor;
- }
- break;
- }
- if (type != XPM_SYMBOLIC && type != XPM_UNKNOWN) {
- if (!found) { /* use this color as default */
- strcpy(useName, colorName);
- found = 1;
- }
- }
- }
-
- gotcolor:
-
- memcpy(&color1, p+1, byteSize);
- p = useName;
- while ((*p != 0) && (*p != '"') && (*p != '\t')) {
- p++;
- }
- *p = 0;
-
- data = 0;
- if (strncasecmp(useName, "none",4)) {
- if (XParseColor(display, colormap, useName, &color) == 0) {
- color.red = color.green = color.blue = 0;
- }
- ((unsigned char *) &data)[0] = color.red>>8;
- ((unsigned char *) &data)[1] = color.green>>8;
- ((unsigned char *) &data)[2] = color.blue>>8;
- ((unsigned char *) &data)[3] = 255;
- }
-
- hPtr = Tcl_CreateHashEntry(&colorTable, (char *) (size_t) color1, &found);
- Tcl_SetHashValue(hPtr, (char *) (size_t) data);
-
- ckfree(colorName);
- ckfree(useName);
- }
-
- Tk_PhotoGetImage(imageHandle, &block);
-
- if (tkimg_PhotoExpand(interp, imageHandle, destX + width, destY + height) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- nchan = block.pixelSize;
- block.pitch = nchan * fileWidth;
- block.width = width;
- block.height = 1;
- block.offset[0] = 0;
- block.offset[1] = 1;
- block.offset[2] = 2;
- block.offset[3] = (nchan == 4 && matte? 3: 0);
- block.pixelPtr = (unsigned char *) ckalloc((unsigned) nchan * width);
-
- i = srcY;
- while (i-- > 0) {
- p = Gets(handle, buffer,MAX_BUFFER);
- while (((p = strchr(p,'\"')) == NULL)) {
- p = Gets(handle, buffer,MAX_BUFFER);
- if (p == NULL) {
- return TCL_ERROR;
- }
- p = buffer;
- }
- }
-
-
- for (h = height; h > 0; h--) {
- p = Gets(handle, buffer,MAX_BUFFER);
- while (((p = strchr(p,'\"')) == NULL)) {
- p = Gets(handle, buffer,MAX_BUFFER);
- if (p == NULL) {
- return TCL_ERROR;
- }
- p = buffer;
- }
- p += byteSize * srcX + 1;
- pixelPtr = block.pixelPtr;
-
- for (i = 0; i < width; ) {
- unsigned int col;
-
- memcpy((char *) &color1, p, byteSize);
- hPtr = Tcl_FindHashEntry(&colorTable, (char *) (size_t) color1);
-
- /*
- * if hPtr == NULL, we have an invalid color entry in the XPM
- * file. We use transparant as default color
- */
- if (hPtr != (Tcl_HashEntry *)NULL)
- col = (unsigned int) (size_t) Tcl_GetHashValue(hPtr);
- else
- col = (unsigned int) 0;
-
- /*
- * we've found a non-transparent pixel, let's search the next
- * transparent pixel and copy this block to the image
- */
- if (col) {
- int len = 0, j;
-
- j = i;
- pixelPtr = block.pixelPtr;
- do {
- memcpy(pixelPtr, &col, block.pixelSize);
- pixelPtr += block.pixelSize;
- i++;
- len++;
- p += byteSize;
-
- if (i < width) {
- memcpy((char *) &color1, p, byteSize);
- hPtr = Tcl_FindHashEntry(&colorTable, (char *) (size_t) color1);
- if (hPtr != (Tcl_HashEntry *)NULL)
- col = (unsigned int) (size_t) Tcl_GetHashValue(hPtr);
- else
- col = (unsigned int) 0;
- }
- } while ((i < width) && col);
- if (tkimg_PhotoPutBlock(interp, imageHandle, &block, destX+j, destY, len, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) {
- result = TCL_ERROR;
- break;
- }
- } else {
- p += byteSize;
- i++;
- }
- }
- destY++;
- }
-
- Tcl_DeleteHashTable(&colorTable);
-
- ckfree((char *) block.pixelPtr);
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ChnRead --
- *
- * This procedure is called by the photo image type to read
- * XPM format data from a channel and write it into a given
- * photo image.
- *
- * Results:
- * A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
- *
- * Side effects:
- * The access position in channel chan is changed, and new
- * data is added to the image given by imageHandle.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ChnRead(interp, chan, fileName, format, imageHandle, destX, destY,
- width, height, srcX, srcY)
- Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
- Tcl_Channel chan; /* The image channel, open for reading. */
- const char *fileName; /* The name of the image file. */
- Tcl_Obj *format; /* User-specified format object, or NULL. */
- Tk_PhotoHandle imageHandle; /* The photo image to write into. */
- int destX, destY; /* Coordinates of top-left pixel in
- * photo image to be written to. */
- int width, height; /* Dimensions of block of photo image to
- * be written to. */
- int srcX, srcY; /* Coordinates of top-left pixel to be used
- * in image being read. */
-{
- tkimg_MFile handle;
- int retVal;
-
- handle.data = (char *) chan;
- handle.state = IMG_CHAN;
-
- tkimg_ReadBuffer (1);
- retVal = CommonRead (interp, &handle, format, imageHandle,
- destX, destY, width, height, srcX, srcY);
- tkimg_ReadBuffer (0);
- return retVal;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ObjRead --
- *
- * This procedure is called by the photo image type to read
- * XPM format data from a string and write it into a given
- * photo image.
- *
- * Results:
- * A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
- *
- * Side effects:
- * New data is added to the image given by imageHandle.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ObjRead(interp, data, format, imageHandle, destX, destY,
- width, height, srcX, srcY)
- Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
- Tcl_Obj *data;
- Tcl_Obj *format; /* User-specified format object, or NULL. */
- Tk_PhotoHandle imageHandle; /* The photo image to write into. */
- int destX, destY; /* Coordinates of top-left pixel in
- * photo image to be written to. */
- int width, height; /* Dimensions of block of photo image to
- * be written to. */
- int srcX, srcY; /* Coordinates of top-left pixel to be used
- * in image being read. */
-{
- tkimg_MFile handle;
-
- handle.data = (char *)tkimg_GetStringFromObj(data, &handle.length);
- handle.state = IMG_STRING;
-
- return CommonRead(interp, &handle, format, imageHandle,
- destX, destY, width, height, srcX, srcY);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ReadXPMFileHeader --
- *
- * This procedure reads the XPM header from the beginning of a
- * XPM file and returns information from the header.
- *
- * Results:
- * The return value is 1 if file "f" appears to start with a valid
- * XPM header, and 0 otherwise. If the header is valid,
- * then *widthPtr and *heightPtr are modified to hold the
- * dimensions of the image and *numColors holds the number of
- * colors and byteSize the number of bytes used for 1 pixel.
- *
- * Side effects:
- * The access position in f advances.
- *
- *----------------------------------------------------------------------
- */
-
-#define UCHAR(c) ((unsigned char) (c))
-
-static int
-ReadXPMFileHeader(handle, widthPtr, heightPtr, numColors, byteSize)
- tkimg_MFile *handle; /* handle to read the header from */
- int *widthPtr, *heightPtr; /* The dimensions of the image are
- * returned here. */
- int *numColors; /* the number of colors is returned here */
- int *byteSize; /* number of bytes per pixel */
-{
- char buffer[MAX_BUFFER];
- char *p;
-
- p = Gets(handle, buffer,MAX_BUFFER);
- if (p == NULL) {
- return 0;
- }
- p = buffer;
- while (*p && isspace(UCHAR(*p))) {
- p++;
- }
- if (strncmp("/* XPM", p, 6) != 0) {
- return 0;
- }
- while ((p = strchr(p,'{')) == NULL) {
- p = Gets(handle, buffer,MAX_BUFFER);
- if (p == NULL) {
- return 0;
- }
- p = buffer;
- }
- while ((p = strchr(p,'"')) == NULL) {
- p = Gets(handle, buffer,MAX_BUFFER);
- if (p == NULL) {
- return 0;
- }
- p = buffer;
- }
- p++;
- while (p && *p && isspace(UCHAR(*p))) {
- p++;
- }
- *widthPtr = strtoul(p, &p, 0);
- if (p == NULL || *widthPtr <= 0) {
- return 0;
- }
- while (p && *p && isspace(UCHAR(*p))) {
- p++;
- }
- *heightPtr = strtoul(p, &p, 0);
- if (p == NULL || *heightPtr <= 0) {
- return 0;
- }
- while (p && *p && isspace(UCHAR(*p))) {
- p++;
- }
- *numColors = strtoul(p, &p, 0);
- if (p == NULL) {
- return 0;
- }
- while (p && *p && isspace(UCHAR(*p))) {
- p++;
- }
- *byteSize = strtoul(p, &p, 0);
- if (p == NULL) {
- return 0;
- }
- return 1;
-}
-
-static char * GetType(colorDefn, type_ret)
- char * colorDefn;
- int * type_ret;
-{
- char * p = colorDefn;
-
- /* skip white spaces */
- while (*p && isspace(UCHAR(*p))) {
- p ++;
- }
-
- /* parse the type */
- if (p[0] != '\0' && p[0] == 'm' &&
- p[1] != '\0' && isspace(UCHAR(p[1]))) {
- *type_ret = XPM_MONO;
- p += 2;
- }
- else if (p[0] != '\0' && p[0] == 'g' &&
- p[1] != '\0' && p[1] == '4' &&
- p[2] != '\0' && isspace(UCHAR(p[2]))) {
- *type_ret = XPM_GRAY_4;
- p += 3;
- }
- else if (p[0] != '\0' && p[0] == 'g' &&
- p[1] != '\0' && isspace(UCHAR(p[1]))) {
- *type_ret = XPM_GRAY;
- p += 2;
- }
- else if (p[0] != '\0' && p[0] == 'c' &&
- p[1] != '\0' && isspace(UCHAR(p[1]))) {
- *type_ret = XPM_COLOR;
- p += 2;
- }
- else if (p[0] != '\0' && p[0] == 's' &&
- p[1] != '\0' && isspace(UCHAR(p[1]))) {
- *type_ret = XPM_SYMBOLIC;
- p += 2;
- }
- else {
- *type_ret = XPM_UNKNOWN;
- return NULL;
- }
-
- return p;
-}
-
-/* colorName is guaranteed to be big enough */
-static char * GetColor(colorDefn, colorName, type_ret)
- char * colorDefn;
- char * colorName; /* if found, name is copied to this array */
- int * type_ret;
-{
- int type;
- char * p;
-
- if (!colorDefn) {
- return NULL;
- }
-
- if ((colorDefn = GetType(colorDefn, &type)) == NULL) {
- /* unknown type */
- return NULL;
- }
- else {
- *type_ret = type;
- }
-
- /* skip white spaces */
- while (*colorDefn && isspace(UCHAR(*colorDefn))) {
- colorDefn ++;
- }
-
- p = colorName;
-
- while (1) {
- int dummy;
-
- while (*colorDefn && !isspace(UCHAR(*colorDefn))) {
- *p++ = *colorDefn++;
- }
-
- if (!*colorDefn) {
- break;
- }
-
- if (GetType(colorDefn, &dummy) == NULL) {
- /* the next string should also be considered as a part of a color
- * name */
-
- while (*colorDefn && isspace(UCHAR(*colorDefn))) {
- *p++ = *colorDefn++;
- }
- } else {
- break;
- }
- if (!*colorDefn) {
- break;
- }
- }
-
- /* Mark the end of the colorName */
- *p = '\0';
-
- return colorDefn;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ChnWrite
- *
- * Writes a XPM image to a file. Just calls CommonWrite
- * with appropriate arguments.
- *
- * Results:
- * Returns the return value of CommonWrite
- *
- * Side effects:
- * A file is (hopefully) created on success.
- *
- *----------------------------------------------------------------------
- */
-static int
-ChnWrite(interp, fileName, format, blockPtr)
- Tcl_Interp *interp;
- const char *fileName;
- Tcl_Obj *format;
- Tk_PhotoImageBlock *blockPtr;
-{
- return CommonWrite(interp, fileName, (Tcl_DString *)NULL, format, blockPtr);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * StringWrite
- *
- * Writes a XPM image to a string. Just calls CommonWrite
- * with appropriate arguments.
- *
- * Results:
- * Returns the return value of CommonWrite
- *
- * Side effects:
- * The Tcl_DString dataPtr is modified on success.
- *
- *----------------------------------------------------------------------
- */
-static int StringWrite(
- Tcl_Interp *interp,
- Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr
-) {
- int result;
- Tcl_DString data;
-
- Tcl_DStringInit(&data);
- result = CommonWrite(interp, "InlineData", &data, format, blockPtr);
- if (result == TCL_OK) {
- Tcl_DStringResult(interp, &data);
- } else {
- Tcl_DStringFree(&data);
- }
- return result;
-}
-
-
-/*
- * Yes, I know these macros are dangerous. But it should work fine
- */
-#define WRITE(buf) { if (!dataPtr) Tcl_Write(chan, buf, -1); else Tcl_DStringAppend(dataPtr, buf, -1);}
-
-/*
- *----------------------------------------------------------------------
- *
- * CommonWrite
- *
- * This procedure writes a XPM image to the file filename
- * (if filename != NULL) or to dataPtr.
- *
- * Results:
- * Returns TCL_OK on success, or TCL_ERROR on error.
- * Possible failures are:
- * 1. cannot access file (permissions or path not found)
- * 2. TkPhotoGetMask fails to retrieve the region mask
- * for the image (should not happen)
- *
- * Side effects:
- * varies (see StringWrite and ChnWrite)
- *
- *----------------------------------------------------------------------
- */
-static int
-CommonWrite(interp, fileName, dataPtr, format, blockPtr)
- Tcl_Interp *interp;
- const char *fileName;
- Tcl_DString *dataPtr;
- Tcl_Obj *format;
- Tk_PhotoImageBlock *blockPtr;
-{
- int x, y, i;
- int found;
- Tcl_Channel chan = (Tcl_Channel) NULL;
- Tcl_HashTable colors;
- Tcl_HashEntry *entry;
- Tcl_HashSearch search;
- unsigned char *pp;
- unsigned char *pixelPtr, *rowPixPtr;
- int ncolors, chars_per_pixel;
- int greenOffset, blueOffset, alphaOffset;
- union {
- ClientData value;
- char component[3];
- } col;
- union {
- ClientData value;
- char component[5];
- } temp;
- char buffer[256], *p, *imgName;
-
- /*
- * xpm_chars[] must be 64 chars long
- */
- static char xpm_chars[] =
- ".#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
- greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
- blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
- alphaOffset = blockPtr->offset[0];
- if (alphaOffset < blockPtr->offset[1]) alphaOffset = blockPtr->offset[1];
- if (alphaOffset < blockPtr->offset[2]) alphaOffset = blockPtr->offset[2];
- if (++alphaOffset < blockPtr->pixelSize) {
- alphaOffset -= blockPtr->offset[0];
- } else {
- alphaOffset = 0;
- }
-
- /* open the output file (if needed) */
- if (!dataPtr) {
- chan = Tcl_OpenFileChannel(interp, (CONST84 char *) fileName, "w", 0644);
- if (!chan) {
- return TCL_ERROR;
- }
- if (Tcl_SetChannelOption (interp, chan, "-buffersize", "131072") != TCL_OK) {
- Tcl_Close(interp, chan);
- return TCL_ERROR;
- }
- }
-
- /* compute image name */
-
- imgName = (char*)ckalloc(strlen(fileName)+1);
- memcpy (imgName, fileName, strlen(fileName)+1);
- p = strrchr(imgName, '/');
- if (p) {
- imgName = p+1;
- }
- p = strrchr(imgName, '\\');
- if (p) {
- imgName = p+1;
- }
- p = strrchr(imgName, ':');
- if (p) {
- imgName = p+1;
- }
- p = strchr(imgName, '.');
- if (p) {
- *p = 0;
- }
- sprintf(buffer, "/* XPM */\nstatic char * %s[] = {\n", imgName);
- WRITE(buffer);
-
- /*
- * Compute size of colortable
- */
- Tcl_InitHashTable(&colors, TCL_ONE_WORD_KEYS);
- ncolors = 0;
- col.value = 0;
- for (y = 0; y < blockPtr->height; y++) {
- pp = blockPtr->pixelPtr + y * blockPtr->pitch + blockPtr->offset[0];
- for (x = blockPtr->width; x >0; x--) {
- if (!alphaOffset || pp[alphaOffset]) {
- col.component[0] = pp[0];
- col.component[1] = pp[greenOffset];
- col.component[2] = pp[blueOffset];
- if (Tcl_FindHashEntry(&colors, (char *) col.value) == NULL) {
- ncolors++;
- entry = Tcl_CreateHashEntry(&colors, (char *) col.value,
- &found);
- }
- }
- pp += blockPtr->pixelSize;
- }
- }
-
- /* compute number of characters per pixel */
- chars_per_pixel = 1;
- i = ncolors;
- while (i > 64) {
- chars_per_pixel++;
- i /= 64;
- }
-
- /* write image info into XPM */
- sprintf(buffer, "\"%d %d %d %d\",\n", blockPtr->width, blockPtr->height,
- ncolors+(alphaOffset != 0), chars_per_pixel);
- WRITE(buffer);
-
- /* write transparent color id if transparency is available*/
- if (alphaOffset) {
- strcpy(temp.component, " ");
- temp.component[chars_per_pixel] = 0;
- sprintf(buffer, "\"%s s None c None\",\n", temp.component);
- WRITE(buffer);
- }
-
- /* write colormap strings */
- entry = Tcl_FirstHashEntry(&colors, &search);
- y = 0;
- temp.component[chars_per_pixel] = 0;
- while (entry) {
- /* compute a color identifier for color #y */
- for (i = 0, x = y++; i < chars_per_pixel; i++, x /= 64)
- temp.component[i] = xpm_chars[x & 63];
-
- /*
- * and put it in the hashtable
- * this is a little bit tricky
- */
- Tcl_SetHashValue(entry, (char *) temp.value);
- pp = (unsigned char *)&entry->key.oneWordValue;
- sprintf(buffer, "\"%s c #%02x%02x%02x\",\n",
- temp.component, pp[0], pp[1], pp[2]);
- WRITE(buffer);
- entry = Tcl_NextHashEntry(&search);
- }
-
- /* write image itself */
- rowPixPtr = blockPtr->pixelPtr + blockPtr->offset[0];
- buffer[chars_per_pixel] = 0;
- for (y = 0; y < blockPtr->height; y++) {
- WRITE("\"");
- pixelPtr = rowPixPtr;
- for (x = 0; x < blockPtr->width; x++) {
- if (!alphaOffset || pixelPtr[alphaOffset]) {
- col.component[0] = pixelPtr[0];
- col.component[1] = pixelPtr[greenOffset];
- col.component[2] = pixelPtr[blueOffset];
- entry = Tcl_FindHashEntry(&colors, (char *) col.value);
- temp.value = Tcl_GetHashValue(entry);
- memcpy(buffer, temp.component, chars_per_pixel);
- } else {
- /* make transparent pixel */
- memcpy(buffer, " ", chars_per_pixel);
- }
- pixelPtr += blockPtr->pixelSize;
- WRITE(buffer);
- }
- if (y == blockPtr->height - 1) {
- WRITE("\"};");
- } else {
- WRITE("\",\n");
- }
- rowPixPtr += blockPtr->pitch;
- }
-
- /* Delete the hash table */
- Tcl_DeleteHashTable(&colors);
-
- /* close the file */
- if (chan) {
- Tcl_Close(interp, chan);
- }
- return TCL_OK;
-}