summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authoroehhar <harald.oehlmann@elmicron.de>2020-06-06 18:07:00 (GMT)
committeroehhar <harald.oehlmann@elmicron.de>2020-06-06 18:07:00 (GMT)
commitbfcb4bfc8122be5094ac6354dc03145e6b123908 (patch)
tree3eeb9ba26def49c3290aabb2946cb721cbd8cfcc /generic
parente265abcfab16c99859b2538e0961693f963c6bcf (diff)
downloadtk-bfcb4bfc8122be5094ac6354dc03145e6b123908.zip
tk-bfcb4bfc8122be5094ac6354dc03145e6b123908.tar.gz
tk-bfcb4bfc8122be5094ac6354dc03145e6b123908.tar.bz2
TIP529 image metadata: changed driver interface: split metadata to in/out object, driver communication dstring, file close flag, reorder all options in a more logical order. Forking intended, will merge later. Thanks Jan, for your work.
Diffstat (limited to 'generic')
-rw-r--r--generic/tk.h27
-rw-r--r--generic/tkImgGIF.c153
-rw-r--r--generic/tkImgPhoto.c295
-rw-r--r--generic/tkStubInit.c3
4 files changed, 230 insertions, 248 deletions
diff --git a/generic/tk.h b/generic/tk.h
index 5aa8998..cd16ce0 100644
--- a/generic/tk.h
+++ b/generic/tk.h
@@ -1441,26 +1441,29 @@ typedef int (Tk_ImageStringWriteProc) (Tcl_Interp *interp, Tcl_Obj *format,
/*
* The following alternate definitions are used with the Tk8.7 file format
- * supporting a metadata dict
+ * supporting a metadata dict, internal dstring and close file flag
*/
typedef struct Tk_PhotoImageFormat87 Tk_PhotoImageFormat87;
-typedef int (Tk_ImageFileMatchProc87) (Tcl_Channel chan, const char *fileName,
- Tcl_Obj *format, int *widthPtr, int *heightPtr, Tcl_Interp *interp,
- Tcl_Obj **metadataPtr);
-typedef int (Tk_ImageStringMatchProc87) (Tcl_Obj *dataObj, Tcl_Obj *format,
- int *widthPtr, int *heightPtr, Tcl_Interp *interp, Tcl_Obj **metadataPtr);
+typedef int (Tk_ImageFileMatchProc87) (Tcl_Interp *interp, Tcl_Channel chan,
+ const char *fileName, Tcl_Obj *format, Tcl_Obj *metadataIn, int *widthPtr,
+ int *heightPtr, int *closeChannelPtr, Tcl_DString *driverInternal);
+typedef int (Tk_ImageStringMatchProc87) (Tcl_Interp *interp, Tcl_Obj *dataObj,
+ Tcl_Obj *format, Tcl_Obj *metadataIn, int *widthPtr, int *heightPtr,
+ Tcl_DString *driverInternal);
typedef int (Tk_ImageFileReadProc87) (Tcl_Interp *interp, Tcl_Channel chan,
- const char *fileName, Tcl_Obj *format, Tk_PhotoHandle imageHandle,
+ const char *fileName, Tcl_Obj *format, Tcl_Obj *metadataIn,
+ Tk_PhotoHandle imageHandle,
int destX, int destY, int width, int height, int srcX, int srcY,
- Tcl_Obj **metadataPtr);
+ Tcl_Obj *metadataOut, Tcl_DString *driverInternal);
typedef int (Tk_ImageStringReadProc87) (Tcl_Interp *interp, Tcl_Obj *dataObj,
- Tcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY,
- int width, int height, int srcX, int srcY, Tcl_Obj **metadataPtr);
+ Tcl_Obj *format, Tcl_Obj *metadataIn, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height, int srcX, int srcY,
+ Tcl_Obj *metadataOut, Tcl_DString *driverInternal);
typedef int (Tk_ImageFileWriteProc87) (Tcl_Interp *interp, const char *fileName,
- Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr, Tcl_Obj *metadata);
+ Tcl_Obj *format, Tcl_Obj *metadataIn, Tk_PhotoImageBlock *blockPtr);
typedef int (Tk_ImageStringWriteProc87) (Tcl_Interp *interp, Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr, Tcl_Obj *metadata);
+ Tcl_Obj *metadataIn, Tk_PhotoImageBlock *blockPtr);
/*
diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c
index 1036bae..f9f0bea 100644
--- a/generic/tkImgGIF.c
+++ b/generic/tkImgGIF.c
@@ -118,29 +118,33 @@ typedef size_t (WriteBytesFunc) (ClientData clientData, const char *bytes,
* The format record for the GIF file format:
*/
-static int FileMatchGIF(Tcl_Channel chan, const char *fileName,
- Tcl_Obj *format, int *widthPtr, int *heightPtr,
- Tcl_Interp *interp, Tcl_Obj **metadataPtr);
+static int FileMatchGIF(Tcl_Interp *interp, Tcl_Channel chan,
+ const char *fileName, Tcl_Obj *format,
+ Tcl_Obj *metadataIn, int *widthPtr, int *heightPtr,
+ int *closeChannelPtr, Tcl_DString *driverInternal);
static int FileReadGIF(Tcl_Interp *interp, Tcl_Channel chan,
const char *fileName, Tcl_Obj *format,
- Tk_PhotoHandle imageHandle, int destX, int destY,
- int width, int height, int srcX, int srcY,
- Tcl_Obj **metadataPtr);
-static int StringMatchGIF(Tcl_Obj *dataObj, Tcl_Obj *format,
- int *widthPtr, int *heightPtr, Tcl_Interp *interp,
- Tcl_Obj **metadataPtr);
+ Tcl_Obj *metadataIn, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height,
+ int srcX, int srcY,
+ Tcl_Obj *metadataOut, Tcl_DString *driverInternal);
+static int StringMatchGIF(Tcl_Interp *interp, Tcl_Obj *dataObj,
+ Tcl_Obj *format, Tcl_Obj *metadataIn, int *widthPtr,
+ int *heightPtr, Tcl_DString *driverInternal);
static int StringReadGIF(Tcl_Interp *interp, Tcl_Obj *dataObj,
- Tcl_Obj *format, Tk_PhotoHandle imageHandle,
+ Tcl_Obj *format, Tcl_Obj *metadataIn,
+ Tk_PhotoHandle imageHandle,
int destX, int destY, int width, int height,
- int srcX, int srcY, Tcl_Obj **metadataPtr);
+ int srcX, int srcY,
+ Tcl_Obj *metadataOut, Tcl_DString *driverInternal);
static int FileWriteGIF(Tcl_Interp *interp, const char *filename,
- Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr,
- Tcl_Obj *metadata);
+ Tcl_Obj *format, Tcl_Obj *metadataIn,
+ Tk_PhotoImageBlock *blockPtr);
static int StringWriteGIF(Tcl_Interp *interp, Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr, Tcl_Obj *metadata);
+ Tcl_Obj *metadataIn, Tk_PhotoImageBlock *blockPtr);
static int CommonWriteGIF(Tcl_Interp *interp, ClientData clientData,
WriteBytesFunc *writeProc, Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr, Tcl_Obj *metadata);
+ Tcl_Obj *metadataIn, Tk_PhotoImageBlock *blockPtr);
Tk_PhotoImageFormat87 tkImgFmtGIF = {
"gif", /* name */
@@ -172,7 +176,7 @@ static int ReadOneByte(Tcl_Interp *interp,
GIFImageConfig *gifConfPtr, Tcl_Channel chan);
static int DoExtension(GIFImageConfig *gifConfPtr,
Tcl_Channel chan, int label, unsigned char *buffer,
- int *transparent, Tcl_Obj *metadata);
+ int *transparent, Tcl_Obj *metadataOut);
static int GetCode(Tcl_Channel chan, int code_size, int flag,
GIFImageConfig *gifConfPtr);
static int GetDataBlock(GIFImageConfig *gifConfPtr,
@@ -350,14 +354,16 @@ static void FlushChar(GIFState_t *statePtr);
static int
FileMatchGIF(
+ Tcl_Interp *dummy, /* not used */
Tcl_Channel chan, /* The image file, open for reading. */
const char *fileName, /* The name of the image file. */
Tcl_Obj *format, /* User-specified format object, or NULL. */
+ Tcl_Obj *metadataIn, /* metadata input, may be NULL */
int *widthPtr, int *heightPtr,
/* The dimensions of the image are returned
* here if the file is a valid raw GIF file. */
- Tcl_Interp *dummy, /* not used */
- Tcl_Obj **metadataPtr) /* metadata to investigate and to return */
+ int *closeChannelPtr, /* Return if the channel may be closed */
+ Tcl_DString *driverInternal)/* memory passed to FileReadGIF */
{
GIFImageConfig gifConf;
(void)fileName;
@@ -393,6 +399,7 @@ FileReadGIF(
Tcl_Channel chan, /* The image file, open for reading. */
const char *fileName, /* The name of the image file. */
Tcl_Obj *format, /* User-specified format object, or NULL. */
+ Tcl_Obj *metadataIn, /* metadata input, may be NULL */
Tk_PhotoHandle imageHandle, /* The photo image to write into. */
int destX, int destY, /* Coordinates of top-left pixel in photo
* image to be written to. */
@@ -400,8 +407,8 @@ FileReadGIF(
* written to. */
int srcX, int srcY, /* Coordinates of top-left pixel to be used in
* image being read. */
- Tcl_Obj **metadataPtr) /* metadata to investigate and to return */
- /* may point to a NULL pointer */
+ Tcl_Obj *metadataOut, /* metadata return dict, may be NULL */
+ Tcl_DString *driverInternal)/* memory passed from FileMatchGIF */
{
int fileWidth, fileHeight, imageWidth, imageHeight;
unsigned int nBytes;
@@ -410,7 +417,6 @@ FileReadGIF(
unsigned char buf[100];
unsigned char *trashBuffer = NULL;
int bitPixel;
- Tcl_Obj *metadata;
int dictSize = 0;
int gifLabel;
unsigned char colorMap[MAXCOLORMAPSIZE][4];
@@ -521,28 +527,6 @@ FileReadGIF(
*/
/*
- * Initialize the metadata dict as an unshared copy of the input metadata.
- * We do not want to modify the metadataPtr in case of an error.
- * So first get a local unshared copy, which is assigned on success.
- */
-
- metadata = *metadataPtr;
- if (metadata == NULL) {
- metadata = Tcl_NewDictObj();
- } else {
- if (Tcl_IsShared(metadata)) {
- metadata = Tcl_DuplicateObj(metadata);
- }
- }
-
- /*
- * Start with a ref count of 1 to delete it in the error case with
- * Tcl_DecrRefCount().
- */
-
- Tcl_IncrRefCount(metadata);
-
- /*
* Search for the frame from the GIF to display.
*/
@@ -567,7 +551,8 @@ FileReadGIF(
goto error;
}
if (DoExtension(gifConfPtr, chan, gifLabel,
- gifConfPtr->workingBuffer, &transparent, metadata) < 0) {
+ gifConfPtr->workingBuffer, &transparent, metadataOut)
+ < 0) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"error reading extension in GIF image", -1));
Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT",
@@ -762,7 +747,8 @@ FileReadGIF(
goto error;
}
if (DoExtension(gifConfPtr, chan, gifLabel,
- gifConfPtr->workingBuffer, &transparent, metadata) < 0) {
+ gifConfPtr->workingBuffer, &transparent, metadataOut)
+ < 0) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"error reading extension in GIF image", -1));
Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT",
@@ -788,30 +774,8 @@ FileReadGIF(
Tcl_SetObjResult(interp, Tcl_NewStringObj(tkImgFmtGIF.name, -1));
result = TCL_OK;
- /*
- * Merge the metadata object if there is data in the dict.
- */
-
- if (TCL_OK != (result = Tcl_DictObjSize(interp,metadata, &dictSize))) {
- goto error;
- }
- if (dictSize > 0) {
- if (*metadataPtr != NULL) {
- Tcl_DecrRefCount(*metadataPtr);
- }
- *metadataPtr = metadata;
- }
-
- /*
- * If a trash buffer has been allocated, free it now.
- */
-
- if (trashBuffer != NULL) {
- ckfree(trashBuffer);
- }
- return result;
-
- error:
+error:
+
/*
* If a trash buffer has been allocated, free it now.
*/
@@ -819,12 +783,6 @@ FileReadGIF(
if (trashBuffer != NULL) {
ckfree(trashBuffer);
}
-
- /*
- * free the metadata object in case of error.
- * Otherwise, it is not freed as the ref count was incremented above.
- */
- Tcl_DecrRefCount(metadata);
return result;
}
@@ -888,12 +846,13 @@ ReadOneByte(
static int
StringMatchGIF(
+ Tcl_Interp *dummy, /* not used */
Tcl_Obj *dataObj, /* the object containing the image data */
Tcl_Obj *format, /* the image format object, or NULL */
+ Tcl_Obj *metadataIn, /* metadata input, may be NULL */
int *widthPtr, /* where to put the string width */
int *heightPtr, /* where to put the string height */
- Tcl_Interp *dummy, /* not used */
- Tcl_Obj **metadataPtr) /* metadata to investigate and to return */
+ Tcl_DString *driverInternal)/* memory to pass to StringReadGIF */
{
unsigned char *data, header[10];
TkSizeT got, length;
@@ -961,11 +920,13 @@ StringReadGIF(
Tcl_Interp *interp, /* interpreter for reporting errors in */
Tcl_Obj *dataObj, /* object containing the image */
Tcl_Obj *format, /* format object, or NULL */
+ Tcl_Obj *metadataIn, /* metadata input, may be NULL */
Tk_PhotoHandle imageHandle, /* the image to write this data into */
int destX, int destY, /* The rectangular region of the */
int width, int height, /* image to copy */
int srcX, int srcY,
- Tcl_Obj **metadataPtr) /* metadata to investigate and to return */
+ Tcl_Obj *metadataOut, /* metadata return dict, may be NULL */
+ Tcl_DString *driverInternal)/* memory passed from StringReadGIF */
{
MFile handle, *hdlPtr = &handle;
TkSizeT length;
@@ -994,7 +955,9 @@ StringReadGIF(
*/
return FileReadGIF(interp, (Tcl_Channel) hdlPtr, xferFormat, format,
- imageHandle, destX, destY, width, height, srcX, srcY, metadataPtr);
+ metadataIn,
+ imageHandle, destX, destY, width, height, srcX, srcY,
+ metadataOut, driverInternal);
}
/*
@@ -1103,7 +1066,7 @@ DoExtension(
int label,
unsigned char *buf, /* defined as 280 byte working buffer */
int *transparent,
- Tcl_Obj *metadata)
+ Tcl_Obj *metadataOut)
{
int count;
/* Prepare extension name
@@ -1139,7 +1102,8 @@ DoExtension(
return -1;
}
/* Detect XMP extension */
- if (0 == memcmp(buf,"XMP DataXMP",11)) {
+ if (NULL != metadataOut
+ && 0 == memcmp(buf,"XMP DataXMP",11)) {
/* XMP format does not use the block structure of GIF
* The data is utf-8 which never contains 0's
* A magic trailer of 258 bytes is added with the following data:
@@ -1180,7 +1144,7 @@ DoExtension(
encoding = Tcl_GetEncoding(NULL, "utf-8");
Tcl_DStringInit(&recodedDString);
Tcl_ExternalToUtfDString(encoding, Tcl_DStringValue(&dataDString), length, &recodedDString);
- result = Tcl_DictObjPut(NULL, metadata,
+ result = Tcl_DictObjPut(NULL, metadataOut,
Tcl_NewStringObj("XMP",-1),
Tcl_NewStringObj(Tcl_DStringValue(&recodedDString),
Tcl_DStringLength(&recodedDString)));
@@ -1208,7 +1172,8 @@ DoExtension(
break;
}
/* Add extension to dict */
- if (extensionStreamName[0] != '\0' ) {
+ if (NULL != metadataOut
+ && extensionStreamName[0] != '\0' ) {
Tcl_Obj *metadataData;
int length = 0;
for (;;) {
@@ -1218,8 +1183,9 @@ DoExtension(
return -1;
case 0: /* end of data */
if (length > 0) {
- if ( TCL_OK != Tcl_DictObjPut(NULL, metadata,
- Tcl_NewByteArrayObj((unsigned char *)extensionStreamName,
+ if ( TCL_OK != Tcl_DictObjPut(NULL, metadataOut,
+ Tcl_NewByteArrayObj(
+ (unsigned char *)extensionStreamName,
strlen(extensionStreamName)), metadataData)) {
return -1;
}
@@ -1906,8 +1872,8 @@ FileWriteGIF(
Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
const char *filename,
Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr,
- Tcl_Obj *metadata)
+ Tcl_Obj *metadata,
+ Tk_PhotoImageBlock *blockPtr)
{
Tcl_Channel chan = NULL;
int result;
@@ -1922,7 +1888,8 @@ FileWriteGIF(
return TCL_ERROR;
}
- result = CommonWriteGIF(interp, chan, WriteToChannel, format, blockPtr, metadata);
+ result = CommonWriteGIF(interp, chan, WriteToChannel, format, metadata,
+ blockPtr);
if (Tcl_Close(interp, chan) == TCL_ERROR) {
return TCL_ERROR;
@@ -1937,15 +1904,15 @@ StringWriteGIF(
Tcl_Interp *interp, /* Interpreter to use for reporting errors and
* returning the GIF data. */
Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr,
- Tcl_Obj *metadata)
+ Tcl_Obj *metadata,
+ Tk_PhotoImageBlock *blockPtr)
{
int result;
Tcl_Obj *objPtr = Tcl_NewObj();
Tcl_IncrRefCount(objPtr);
result = CommonWriteGIF(interp, objPtr, WriteToByteArray, format,
- blockPtr, metadata);
+ metadata, blockPtr);
if (result == TCL_OK) {
Tcl_SetObjResult(interp, objPtr);
}
@@ -1985,8 +1952,8 @@ CommonWriteGIF(
ClientData handle,
WriteBytesFunc *writeProc,
Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr,
- Tcl_Obj *metadata)
+ Tcl_Obj *metadata,
+ Tk_PhotoImageBlock *blockPtr)
{
GifWriterState state;
int resolution;
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c
index ef5f38d..c79f128 100644
--- a/generic/tkImgPhoto.c
+++ b/generic/tkImgPhoto.c
@@ -200,16 +200,21 @@ static char * ImgGetPhoto(PhotoMaster *masterPtr,
struct SubcommandOptions *optPtr);
static int MatchFileFormat(Tcl_Interp *interp, Tcl_Channel chan,
const char *fileName, Tcl_Obj *formatString,
- Tcl_Obj **metadataObjPtr,
+ Tcl_Obj *metadataInObj,
+ Tcl_Obj *metadataOutObj,
Tk_PhotoImageFormat **imageFormatPtr,
Tk_PhotoImageFormat87 **imageFormat87Ptr,
- int *widthPtr, int *heightPtr, int *oldformat);
+ int *widthPtr, int *heightPtr, int *oldformat,
+ int *closeChannelPtr,
+ Tcl_DString *driverInternalPtr);
static int MatchStringFormat(Tcl_Interp *interp, Tcl_Obj *data,
Tcl_Obj *formatString,
- Tcl_Obj **metadataObjPtr,
+ Tcl_Obj *metadataInObj,
+ Tcl_Obj *metadataOutObj,
Tk_PhotoImageFormat **imageFormatPtr,
Tk_PhotoImageFormat87 **imageFormat87Ptr,
- int *widthPtr, int *heightPtr, int *oldformat);
+ int *widthPtr, int *heightPtr, int *oldformat,
+ Tcl_DString *driverInternalPtr);
static const char * GetExtension(const char *path);
/*
@@ -851,7 +856,7 @@ ImgPhotoCmd(
if (stringWriteProc == NULL) {
result = (stringWriteProc87)(interp,
- options.format, &block, options.metadata);
+ options.format, options.metadata, &block);
} else if (oldformat) {
Tcl_DString buffer;
typedef int (*OldStringWriteProc)(Tcl_Interp *interp,
@@ -949,9 +954,9 @@ ImgPhotoCmd(
}
case PHOTO_PUT: {
- Tcl_Obj *format, *data, *metadata;
int result;
-
+ Tcl_Obj *format, *data;
+ Tcl_DString driverInternalDString;
/*
* photo put command - first parse the options.
*/
@@ -970,30 +975,24 @@ ImgPhotoCmd(
Tcl_WrongNumArgs(interp, 2, objv, "data ?-option value ...?");
return TCL_ERROR;
}
-
+
/*
- * Prepare a metadata dict.
- * If the object pointer points to NULL, there is no metadata dict on input.
- * The match and read calls may modify it and change it from NULL.
- * The refcount of options.metadata is >= 1
+ * Prepare memory connection between format match and read function
*/
- if (options.metadata == NULL) {
- metadata = NULL;
- } else {
- metadata = options.metadata;
- Tcl_IncrRefCount(metadata);
- }
+
+ Tcl_DStringInit(&driverInternalDString);
/*
* See if there's a format that can read the data
*/
if (MatchStringFormat(interp, objv[2], options.format,
- &metadata, &imageFormat,
- &imageFormat87, &imageWidth, &imageHeight, &oldformat)
+ options.metadata, NULL, &imageFormat,
+ &imageFormat87, &imageWidth, &imageHeight, &oldformat,
+ &driverInternalDString)
!= TCL_OK) {
result = TCL_ERROR;
- goto putsCleanup;
+ goto putCleanup;
}
if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
@@ -1021,18 +1020,21 @@ ImgPhotoCmd(
options.toX2 - options.toX,
options.toY2 - options.toY, 0, 0) != TCL_OK) {
result = TCL_ERROR;
- goto putsCleanup;
+ goto putCleanup;
}
} else {
if (imageFormat87->stringReadProc(interp, data, format,
+ options.metadata,
(Tk_PhotoHandle) masterPtr, options.toX, options.toY,
options.toX2 - options.toX,
options.toY2 - options.toY, 0, 0,
- &metadata) != TCL_OK) {
- result = TCL_ERROR;
- goto putsCleanup;
+ NULL, &driverInternalDString)
+ != TCL_OK) {
+ result = TCL_ERROR;
+ goto putCleanup;
}
}
+
/*
* SB: is the next line really needed? The stringReadProc
* writes image data with Tk_PhotoPutBlock(), which in turn
@@ -1040,15 +1042,18 @@ ImgPhotoCmd(
* IMAGE_CHANGED bit.
*/
masterPtr->flags |= IMAGE_CHANGED;
+
result = TCL_OK;
-putsCleanup:
- if (metadata != NULL)
- Tcl_DecrRefCount(metadata);
+putCleanup:
+ Tcl_DStringFree(&driverInternalDString);
return result;
+
}
case PHOTO_READ: {
- Tcl_Obj *format, *metadata;
+ Tcl_Obj *format;
int result;
+ int closeChannel = 0;
+ Tcl_DString driverInternalDString;
/*
* photo read command - first parse the options specified.
@@ -1101,22 +1106,16 @@ putsCleanup:
}
/*
- * Prepare a metadata dict.
- * If the object pointer points to NULL, there is no metadata dict on input.
- * The match and read calls may modify it and change it from NULL.
- * ToDo: think about ref counting and freeing it below
- */
- if (options.metadata == NULL) {
- metadata = NULL;
- } else {
- metadata = options.metadata;
- Tcl_IncrRefCount(metadata);
- }
-
+ * Prepare memory connection between format match and read function
+ */
+
+ Tcl_DStringInit(&driverInternalDString);
+ closeChannel = 0;
if (MatchFileFormat(interp, chan,
Tcl_GetString(options.name), options.format,
- &metadata, &imageFormat,
- &imageFormat87, &imageWidth, &imageHeight, &oldformat)
+ options.metadata, NULL, &imageFormat,
+ &imageFormat87, &imageWidth, &imageHeight, &oldformat,
+ &closeChannel, &driverInternalDString)
!= TCL_OK) {
result = TCL_ERROR;
goto readCleanup;
@@ -1177,13 +1176,12 @@ putsCleanup:
} else {
result = imageFormat87->fileReadProc(interp, chan,
Tcl_GetString(options.name),
- format, (Tk_PhotoHandle) masterPtr, options.toX,
- options.toY, width, height, options.fromX, options.fromY,
- &metadata);
+ format, options.metadata, (Tk_PhotoHandle) masterPtr,
+ options.toX, options.toY, width, height, options.fromX,
+ options.fromY, NULL, &driverInternalDString);
}
readCleanup:
- if (metadata != NULL)
- Tcl_DecrRefCount(metadata);
+ Tcl_DStringFree(&driverInternalDString);
if (chan != NULL) {
Tcl_Close(NULL, chan);
}
@@ -1564,8 +1562,8 @@ readCleanup:
Tcl_GetString(options.name), format, &block);
} else {
result = imageFormat87->fileWriteProc(interp,
- Tcl_GetString(options.name), format, &block,
- options.metadata);
+ Tcl_GetString(options.name), format, options.metadata,
+ &block);
}
if (options.background) {
Tk_FreeColor(options.background);
@@ -1944,7 +1942,8 @@ ImgPhotoConfigureMaster(
{
PhotoInstance *instancePtr;
const char *oldFileString, *oldPaletteString;
- Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL, *metadata = NULL;
+ Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL,
+ *metadataIn = NULL, *metadataOut = NULL;
Tcl_Obj *tempdata, *tempformat;
TkSizeT length;
int i, j, result, imageWidth, imageHeight, oldformat;
@@ -1953,6 +1952,8 @@ ImgPhotoConfigureMaster(
Tk_PhotoImageFormat *imageFormat;
Tk_PhotoImageFormat87 *imageFormat87;
const char **args;
+ Tcl_DString driverInternalDString;
+ int closeChannel;
args = (const char **)ckalloc((objc + 1) * sizeof(char *));
for (i = 0, j = 0; i < objc; i++,j++) {
@@ -1987,7 +1988,7 @@ ImgPhotoConfigureMaster(
} else if ((args[j][1] == 'm') &&
!strncmp(args[j], "-metadata", length)) {
if (++i < objc) {
- metadata = objv[i];
+ metadataIn = objv[i];
j--;
} else {
ckfree(args);
@@ -2002,6 +2003,12 @@ ImgPhotoConfigureMaster(
}
/*
+ * Prepare memory connection between format match and read function
+ */
+
+ Tcl_DStringInit(&driverInternalDString);
+
+ /*
* Save the current values for fileString and dataString, so we can tell
* if the user specifies them anew. IMPORTANT: if the format changes we
* have to interpret "-file" and "-data" again as well! It might be that
@@ -2078,29 +2085,30 @@ ImgPhotoConfigureMaster(
}
masterPtr->format = format;
}
- if (metadata) {
+ if (metadataIn) {
/*
* make -metadata a dict and take it if keys in.
* Otherwise set a metadata null pointer.
*/
int dictSize;
- if (TCL_OK != Tcl_DictObjSize(interp,metadata, &dictSize)) {
+ if (TCL_OK != Tcl_DictObjSize(interp,metadataIn, &dictSize)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"value for \"-metadata\" not a dict", -1));
Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
"UNRECOGNIZED_DATA", NULL);
return TCL_ERROR;
}
+
if (dictSize > 0) {
- Tcl_IncrRefCount(metadata);
+ Tcl_IncrRefCount(metadataIn);
} else {
- metadata = NULL;
+ metadataIn = NULL;
}
if (masterPtr->metadata) {
Tcl_DecrRefCount(masterPtr->metadata);
}
- masterPtr->metadata = metadata;
+ masterPtr->metadata = metadataIn;
}
/*
* Set the image to the user-requested size, if any, and make sure storage
@@ -2123,6 +2131,7 @@ ImgPhotoConfigureMaster(
if ((masterPtr->fileString != NULL)
&& ((masterPtr->fileString != oldFileString)
|| (masterPtr->format != oldFormat))) {
+
/*
* Prevent file system access in a safe interpreter.
*/
@@ -2141,6 +2150,8 @@ ImgPhotoConfigureMaster(
goto errorExit;
}
+ closeChannel = 0;
+
/*
* -translation binary also sets -encoding binary
*/
@@ -2148,9 +2159,10 @@ ImgPhotoConfigureMaster(
if ((Tcl_SetChannelOption(interp, chan,
"-translation", "binary") != TCL_OK) ||
(MatchFileFormat(interp, chan, masterPtr->fileString,
- masterPtr->format, &(masterPtr->metadata),
+ masterPtr->format, masterPtr->metadata, NULL,
&imageFormat, &imageFormat87,
- &imageWidth, &imageHeight, &oldformat) != TCL_OK)) {
+ &imageWidth, &imageHeight, &oldformat, &closeChannel,
+ &driverInternalDString) != TCL_OK)) {
Tcl_Close(NULL, chan);
goto errorExit;
}
@@ -2173,10 +2185,10 @@ ImgPhotoConfigureMaster(
0, 0, imageWidth, imageHeight, 0, 0);
} else {
result = imageFormat87->fileReadProc(interp, chan,
- masterPtr->fileString, tempformat,
+ masterPtr->fileString, tempformat, masterPtr->metadata,
(Tk_PhotoHandle) masterPtr,
0, 0, imageWidth, imageHeight, 0, 0,
- &(masterPtr->metadata));
+ metadataOut, &driverInternalDString);
}
Tcl_Close(NULL, chan);
if (result != TCL_OK) {
@@ -2196,9 +2208,9 @@ ImgPhotoConfigureMaster(
|| (masterPtr->format != oldFormat))) {
if (MatchStringFormat(interp, masterPtr->dataString,
- masterPtr->format, &(masterPtr->metadata),
+ masterPtr->format, masterPtr->metadata, NULL,
&imageFormat, &imageFormat87, &imageWidth,
- &imageHeight, &oldformat) != TCL_OK) {
+ &imageHeight, &oldformat, &driverInternalDString) != TCL_OK) {
goto errorExit;
}
if (ImgPhotoSetSize(masterPtr, imageWidth, imageHeight) != TCL_OK) {
@@ -2222,9 +2234,18 @@ ImgPhotoConfigureMaster(
goto errorExit;
}
} else {
+
+ /*
+ * Flag that we want the metadata result dict
+ */
+
+ metadataOut = Tcl_NewDictObj();
+ Tcl_IncrRefCount(metadataOut);
+
if (imageFormat87->stringReadProc(interp, tempdata, tempformat,
- (Tk_PhotoHandle) masterPtr, 0, 0, imageWidth, imageHeight,
- 0, 0, &(masterPtr->metadata)) != TCL_OK) {
+ masterPtr->metadata, (Tk_PhotoHandle) masterPtr, 0, 0,
+ imageWidth, imageHeight, 0, 0, metadataOut,
+ &driverInternalDString) != TCL_OK) {
goto errorExit;
}
}
@@ -2234,6 +2255,48 @@ ImgPhotoConfigureMaster(
}
/*
+ * Merge driver returned metadata and master metadata
+ */
+ if (metadataOut != NULL) {
+ int dictSize;
+ if (TCL_OK != Tcl_DictObjSize(interp,metadataOut, &dictSize)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "driver metadata not a dict", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "UNRECOGNIZED_DATA", NULL);
+ goto errorExit;
+ }
+ if (dictSize > 0) {
+
+ /*
+ * We have driver return metadata
+ */
+
+ if (masterPtr->metadata == NULL) {
+ masterPtr->metadata = metadataOut;
+ metadataOut = NULL;
+ } else {
+ Tcl_DictSearch search;
+ Tcl_Obj *key, *value;
+ int done;
+
+ if (Tcl_IsShared(masterPtr->metadata)) {
+ masterPtr->metadata = Tcl_DuplicateObj(masterPtr->metadata);
+ Tcl_IncrRefCount(masterPtr->metadata);
+ }
+
+ if (Tcl_DictObjFirst(interp, metadataOut, &search, &key, &value,
+ &done) != TCL_OK) {
+ goto errorExit;
+ }
+ for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) {
+ Tcl_DictObjPut(interp, masterPtr->metadata, key, value);
+ }
+ }
+ }
+ }
+
+ /*
* Enforce a reasonable value for gamma.
*/
@@ -2265,24 +2328,32 @@ ImgPhotoConfigureMaster(
masterPtr->height, masterPtr->width, masterPtr->height);
masterPtr->flags &= ~IMAGE_CHANGED;
+ Tcl_DStringInit(&driverInternalDString);
if (oldData != NULL) {
Tcl_DecrRefCount(oldData);
}
if (oldFormat != NULL) {
Tcl_DecrRefCount(oldFormat);
}
+ if (metadataOut != NULL) {
+ Tcl_DecrRefCount(metadataOut);
+ }
ToggleComplexAlphaIfNeeded(masterPtr);
return TCL_OK;
errorExit:
+ Tcl_DStringInit(&driverInternalDString);
if (oldData != NULL) {
Tcl_DecrRefCount(oldData);
}
if (oldFormat != NULL) {
Tcl_DecrRefCount(oldFormat);
}
+ if (metadataOut != NULL) {
+ Tcl_DecrRefCount(metadataOut);
+ }
return TCL_ERROR;
}
@@ -2635,7 +2706,8 @@ MatchFileFormat(
Tcl_Channel chan, /* The image file, open for reading. */
const char *fileName, /* The name of the image file. */
Tcl_Obj *formatObj, /* User-specified format string, or NULL. */
- Tcl_Obj **metadataObjPtr, /* User-specified metadata and return it */
+ Tcl_Obj *metadataInObj, /* User-specified metadata, may be NULL */
+ Tcl_Obj *metadataOutObj, /* metadata to return, may be NULL */
Tk_PhotoImageFormat **imageFormatPtr,
/* A pointer to the photo image format record
* is returned here. For format87, this is set
@@ -2647,7 +2719,10 @@ MatchFileFormat(
int *widthPtr, int *heightPtr,
/* The dimensions of the image are returned
* here. */
- int *oldformat) /* Returns 1 if the old image API is used. */
+ int *oldformat, /* Returns 1 if the old image API is used. */
+ int *closeChannelPtr, /* Is set to 1 if channel can be closed */
+ Tcl_DString *driverInternalPtr)/* Memory to be passed to the corresponding
+ * ReadFileFormat function */
{
int matched = 0, useoldformat = 0, use87format = 0;
Tk_PhotoImageFormat *formatPtr;
@@ -2769,8 +2844,9 @@ MatchFileFormat(
if (format87Ptr->fileMatchProc != NULL) {
(void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET);
- if (format87Ptr->fileMatchProc(chan, fileName, formatObj,
- widthPtr, heightPtr, interp, metadataObjPtr)) {
+ if (format87Ptr->fileMatchProc(interp, chan, fileName, formatObj,
+ metadataInObj, widthPtr, heightPtr, closeChannelPtr,
+ driverInternalPtr)) {
if (*widthPtr < 1) {
*widthPtr = 1;
}
@@ -2833,7 +2909,8 @@ MatchStringFormat(
Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
Tcl_Obj *data, /* Object containing the image data. */
Tcl_Obj *formatObj, /* User-specified format string, or NULL. */
- Tcl_Obj **metadataObjPtr, /* User-specified metadata and return it */
+ Tcl_Obj *metadataInObj, /* User-specified metadata, may be NULL */
+ Tcl_Obj *metadataOutObj, /* metadata output dict, may be NULL */
Tk_PhotoImageFormat **imageFormatPtr,
/* A pointer to the photo image format record
* is returned here. For format87, this is set
@@ -2845,7 +2922,9 @@ MatchStringFormat(
int *widthPtr, int *heightPtr,
/* The dimensions of the image are returned
* here. */
- int *oldformat) /* Returns 1 if the old image API is used. */
+ int *oldformat, /* Returns 1 if the old image API is used. */
+ Tcl_DString *driverInternalPtr)/* Memory to be passed to the corresponding
+ * ReadFileFormat function */
{
int matched = 0, useoldformat = 0, use87format = 0;
Tk_PhotoImageFormat *formatPtr, *defaultFormatPtr = NULL;
@@ -2959,15 +3038,15 @@ MatchStringFormat(
}
if ((format87Ptr->stringMatchProc != NULL)
&& (format87Ptr->stringReadProc != NULL)
- && format87Ptr->stringMatchProc(
- data, formatObj,
- widthPtr, heightPtr, interp, metadataObjPtr)) {
+ && format87Ptr->stringMatchProc(interp, data, formatObj,
+ metadataInObj, widthPtr, heightPtr,
+ driverInternalPtr)) {
break;
}
}
}
- if (formatPtr == NULL && format87Ptr == 0) {
+ if (formatPtr == NULL && format87Ptr == NULL) {
/*
* Try the default format as last resort (only if no -format option
* was passed).
@@ -4085,72 +4164,6 @@ Tk_PhotoSetSize(
/*
*----------------------------------------------------------------------
*
- * Tk_PhotoGetMetadata --
- *
- * This function is called to obtain the metadata object of a photo
- * image.
- *
- * Results:
- * The image's metadata object pointer.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj *
-Tk_PhotoGetMetadata(
- Tk_PhotoHandle handle) /* Handle for the image whose dimensions are
- * requested. */
-{
- PhotoMaster *masterPtr = (PhotoMaster *) handle;
-
- return masterPtr->metadata;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tk_PhotoSetMetadata --
- *
- * This function is called to obtain to set the metadata object of a
- * photo image.
- *
- * Results:
- * None
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tk_PhotoSetMetadata(
- Tk_PhotoHandle handle, /* Handle for the image whose dimensions are
- * requested. */
- Tcl_Obj *metadata)
-{
- PhotoMaster *masterPtr = (PhotoMaster *) handle;
- /*
- * Free current object if present
- */
- if(masterPtr->metadata != NULL) {
- Tcl_DecrRefCount(masterPtr->metadata);
- }
- /*
- * Increment ref count of new object to get it
- */
- if (metadata != NULL) {
- Tcl_IncrRefCount(metadata);
- }
- masterPtr->metadata = metadata;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkGetPhotoValidRegion --
*
* This function is called to get the part of the photo where there is
diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c
index 461ca1e..e52d404 100644
--- a/generic/tkStubInit.c
+++ b/generic/tkStubInit.c
@@ -1301,8 +1301,7 @@ const TkStubs tkStubs = {
Tk_Interp, /* 271 */
Tk_CreateOldImageType, /* 272 */
Tk_CreateOldPhotoImageFormat, /* 273 */
- Tk_PhotoGetMetadata, /* 274 */
- Tk_PhotoSetMetadata, /* 275 */
+ Tk_CreatePhotoImageFormat87 /* 274 */
};
/* !END!: Do not edit above this line. */