diff options
author | oehhar <harald.oehlmann@elmicron.de> | 2020-06-06 18:07:00 (GMT) |
---|---|---|
committer | oehhar <harald.oehlmann@elmicron.de> | 2020-06-06 18:07:00 (GMT) |
commit | bfcb4bfc8122be5094ac6354dc03145e6b123908 (patch) | |
tree | 3eeb9ba26def49c3290aabb2946cb721cbd8cfcc /generic | |
parent | e265abcfab16c99859b2538e0961693f963c6bcf (diff) | |
download | tk-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.h | 27 | ||||
-rw-r--r-- | generic/tkImgGIF.c | 153 | ||||
-rw-r--r-- | generic/tkImgPhoto.c | 295 | ||||
-rw-r--r-- | generic/tkStubInit.c | 3 |
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. */ |