diff options
author | Mikhail Teterin <mi@FreeBSD.org> | 2014-11-18 23:54:17 +0000 |
---|---|---|
committer | Mikhail Teterin <mi@FreeBSD.org> | 2014-11-18 23:54:17 +0000 |
commit | bef44812562739bbe3621ef7270dde65aed534ff (patch) | |
tree | 7fceea44817b66596d03a186578019a79eab21d5 /graphics/gdtclft | |
parent | 817763946d970c5958724d3a1fba9457500c2ee4 (diff) | |
download | ports-bef44812562739bbe3621ef7270dde65aed534ff.tar.gz ports-bef44812562739bbe3621ef7270dde65aed534ff.zip |
Notes
Diffstat (limited to 'graphics/gdtclft')
-rw-r--r-- | graphics/gdtclft/Makefile | 37 | ||||
-rw-r--r-- | graphics/gdtclft/distinfo | 2 | ||||
-rw-r--r-- | graphics/gdtclft/files/Makefile.bsd | 33 | ||||
-rw-r--r-- | graphics/gdtclft/files/patch-improve | 1362 | ||||
-rw-r--r-- | graphics/gdtclft/pkg-descr | 10 |
5 files changed, 1444 insertions, 0 deletions
diff --git a/graphics/gdtclft/Makefile b/graphics/gdtclft/Makefile new file mode 100644 index 000000000000..35e955d0ca8a --- /dev/null +++ b/graphics/gdtclft/Makefile @@ -0,0 +1,37 @@ +# Created by: Mikhail Teterin <mi@aldan.algebra.com> +# $FreeBSD$ + +PORTNAME= Gdtclft +PORTVERSION= 2.2.5 +PORTREVISION= 14 +CATEGORIES= graphics tcl +MASTER_SITES= +DISTNAME= ${PORTNAME}${PORTVERSION} + +MAINTAINER= mi@aldan.algebra.com +COMMENT= TCL interface to the Thomas Boutell's Gd library + +LIB_DEPENDS= libgd.so:${PORTSDIR}/graphics/gd + +USES= tcl:84+ uidfix + +MAKEFILE= ${FILESDIR}/Makefile.bsd +MAKE_ENV= TCL_VER=${TCL_VER} MKDIR="${MKDIR}" \ + TCL_SHLIB_VER=${TCL_SHLIB_VER} \ + INSTALL_DATA="${INSTALL_DATA}" STAGEDIR="${STAGEDIR}" +ALL_TARGET= all + +MANNPAGE= gdtclft.n +GDTCLDIR= lib/tcl${TCL_VER}/gdtclft +PLIST_DIRS= ${GDTCLDIR} +PLIST_FILES= ${GDTCLDIR}/pkgIndex.tcl +PLIST_FILES+= ${GDTCLDIR}/libGdtclft2.so +PLIST_FILES+= man/mann/${MANNPAGE}.gz + +post-patch: + ${REINPLACE_CMD} -Ee 's,[[:space:]]+$$,,' ${WRKSRC}/${MANNPAGE} + +post-install: + ${GZIP_CMD} -9 -f < ${WRKSRC}/${MANNPAGE} > ${STAGEDIR}${PREFIX}/man/mann/${MANNPAGE}.gz + +.include <bsd.port.mk> diff --git a/graphics/gdtclft/distinfo b/graphics/gdtclft/distinfo new file mode 100644 index 000000000000..d79f8eddbc8f --- /dev/null +++ b/graphics/gdtclft/distinfo @@ -0,0 +1,2 @@ +SHA256 (Gdtclft2.2.5.tar.gz) = 34aa5414f74aa93269c03268e95f2cde85836488e8b6820c5b8bb6a088bc698e +SIZE (Gdtclft2.2.5.tar.gz) = 47257 diff --git a/graphics/gdtclft/files/Makefile.bsd b/graphics/gdtclft/files/Makefile.bsd new file mode 100644 index 000000000000..a75addfe8e40 --- /dev/null +++ b/graphics/gdtclft/files/Makefile.bsd @@ -0,0 +1,33 @@ +PACKAGE = Gdtclft +VERSION = 2.3 +SHLIB_NAME = lib${PACKAGE}2.so + +SRCS = gdCmd.c + +LOCALBASE ?=/usr/local +PREFIX ?=/usr/local +TCL_VER ?=8.4 +WARNS = 3 + +LDADD = -L${LOCALBASE}/lib -lgd -lpng -lz -lm -ltcl${TCL_SHLIB_VER} + +CFLAGS +=-I${LOCALBASE}/include/tcl${TCL_VER} -I${LOCALBASE}/include/gd +CFLAGS +=-DNDEBUG -Wall -I. -I${LOCALBASE}/include +CFLAGS +=-DVERSION=\"${VERSION}\" + +all: pkgIndex.tcl + +pkgIndex.tcl: + echo 'package ifneeded $(PACKAGE) $(VERSION) [list load [file join $$dir $(SHLIB_NAME)] $(PACKAGE)]' > pkgIndex.tcl + +DIR = lib/tcl${TCL_VER}/gdtclft +LIBDIR = ${PREFIX}/${DIR} +MANDIR = ${PREFIX}/man/man + +${STAGEDIR}${LIBDIR}: + ${MKDIR} $@ + +beforeinstall: ${STAGEDIR}${LIBDIR} + ${INSTALL_DATA} pkgIndex.tcl ${STAGEDIR}${LIBDIR} + +.include <bsd.lib.mk> diff --git a/graphics/gdtclft/files/patch-improve b/graphics/gdtclft/files/patch-improve new file mode 100644 index 000000000000..8c53a2d6a7ea --- /dev/null +++ b/graphics/gdtclft/files/patch-improve @@ -0,0 +1,1362 @@ +This patch adds support for GIF, XPM, WBMP, and JPEG file formats, which +are supported by the underlying GD. + +GIF, JPEG, and WBMP formats are also added as _output_ formats. + +Also, in case of file-opening failure, a useful error string is +returned. + +Dispense with our own table of handles and use Tcl-objects capability +instead. + +Compiler-warning fixes now allow compiling on FreeBSD with WARNS=3. + +When used in a safe interpreter, the functionality is limited to +disallow access to filesystem. + +Use freely and get yourself a pademelon... + + -mi (http://cafepress.com/buy/pademelon?pid=5934485) + +--- gdCmd.c Fri Aug 4 17:11:05 2000 ++++ gdCmd.c 2014-04-29 19:42:13.000000000 -0400 +@@ -19,4 +19,5 @@ + */ + ++#include <errno.h> + #include <stdio.h> + #include <string.h> +@@ -24,5 +25,4 @@ + #include <tcl.h> + #include "gd.h" +-#include "gdhandle.h" + + #ifdef WIN32 +@@ -30,28 +30,47 @@ + #endif + +-void *GDHandleTable; ++static Tcl_UpdateStringProc GdPtrTypeUpdate; ++static Tcl_SetFromAnyProc GdPtrTypeSet; ++static Tcl_ObjType GdPtrType = { ++ .name = "gd", ++ .updateStringProc = GdPtrTypeUpdate, ++ .setFromAnyProc = GdPtrTypeSet ++}; ++#define IMGPTR(O) (O->internalRep.otherValuePtr) + +-/* global data */ +-typedef struct { +- tblHeader_pt handleTbl; +-} GdData; ++/* The only two symbols exported */ ++Tcl_AppInitProc Gdtclft_Init, Gdtclft_SafeInit; + +-static int tclGdCreateCmd(), tclGdDestroyCmd(), tclGdWriteCmd(), +- tclGdColorCmd(), tclGdInterlaceCmd(), tclGdSetCmd(), tclGdLineCmd(), +- tclGdRectCmd(), tclGdArcCmd(), tclGdFillCmd(), tclGdSizeCmd(), +- tclGdTextCmd(), tclGdCopyCmd(), tclGdGetCmd(), +- tclGdBrushCmd(), tclGdStyleCmd(), tclGdTileCmd(), tclGdPolygonCmd(), +- tclGdColorNewCmd(), tclGdColorExactCmd(), tclGdColorClosestCmd(), +- tclGdColorResolveCmd(), tclGdColorFreeCmd(), tclGdColorTranspCmd(), +- tclGdColorGetCmd(), tclGdWriteBufCmd(); ++typedef int (GdDataFunction)(Tcl_Interp *interp, ++ int argc, Tcl_Obj *CONST objv[]); ++typedef int (GdImgFunction)(Tcl_Interp *interp, gdImagePtr gdImg, ++ int argc, const int args[]); ++ ++static GdDataFunction tclGdCreateCmd, tclGdDestroyCmd, tclGdWriteCmd, ++ tclGdColorCmd, tclGdInterlaceCmd, tclGdSetCmd, tclGdLineCmd, ++ tclGdRectCmd, tclGdArcCmd, tclGdFillCmd, tclGdSizeCmd, ++ tclGdTextCmd, tclGdCopyCmd, tclGdGetCmd, tclGdWriteBufCmd, ++ tclGdBrushCmd, tclGdStyleCmd, tclGdTileCmd, tclGdPolygonCmd; ++ ++static GdImgFunction tclGdColorNewCmd, tclGdColorExactCmd, ++ tclGdColorClosestCmd, tclGdColorResolveCmd, tclGdColorFreeCmd, ++ tclGdColorTranspCmd, tclGdColorGetCmd; + + typedef struct { +- char *cmd; +- int (*f)(); +- int minargs, maxargs; +- int subcmds; +- int ishandle; +- char *usage; +-} cmdOptions; ++ const char *cmd; ++ GdDataFunction *f; ++ unsigned int minargs, maxargs; ++ unsigned int subcmds; ++ unsigned int ishandle; ++ unsigned int unsafearg; ++ const char *usage; ++} cmdDataOptions; ++ ++typedef struct { ++ const char *cmd; ++ GdImgFunction *f; ++ unsigned int minargs, maxargs; ++ const char *usage; ++} cmdImgOptions; + + typedef struct { +@@ -60,53 +79,81 @@ + } BuffSinkContext; + +-static cmdOptions subcmdVec[] = { +- {"create", tclGdCreateCmd, 2, 2, 0, 0, +- "width height"}, +- {"createFromPNG", tclGdCreateCmd, 1, 1, 0, 0, ++static cmdDataOptions subcmdVec[] = { ++ {"create", tclGdCreateCmd, 2, 3, 0, 0, 0, ++ "width height ?true?"}, ++ {"createFromPNG", tclGdCreateCmd, 1, 1, 0, 0, 2, ++ "filehandle"}, ++ {"createFromGIF", tclGdCreateCmd, 1, 1, 0, 0, 2, ++ "filehandle"}, ++ {"createFromGD", tclGdCreateCmd, 1, 1, 0, 0, 2, + "filehandle"}, +- {"createFromGD", tclGdCreateCmd, 1, 1, 0, 0, ++ {"createFromGD2", tclGdCreateCmd, 1, 1, 0, 0, 2, + "filehandle"}, +- {"createFromXBM", tclGdCreateCmd, 1, 1, 0, 0, ++ {"createFromXBM", tclGdCreateCmd, 1, 1, 0, 0, 2, ++ "filehandle"}, ++#ifdef NOX11 ++ {"createFromXPM-NOT-AVAILABLE", tclGdCreateCmd, 1, 1, 0, 0, 2, ++ "filename"}, ++#else ++ {"createFromXPM", tclGdCreateCmd, 1, 1, 0, 0, 2, ++ "filename"}, ++#endif ++ {"createFromJPG", tclGdCreateCmd, 1, 1, 0, 0, 2, ++ "filehandle"}, ++ {"createFromJPEG", tclGdCreateCmd, 1, 1, 0, 0, 2, ++ "filehandle"}, ++ {"createFromWBMP", tclGdCreateCmd, 1, 1, 0, 0, 2, + "filehandle"}, + +- {"destroy", tclGdDestroyCmd, 1, 1, 0, 1, ++ {"destroy", tclGdDestroyCmd, 1, 1, 0, 1, 0, + "gdhandle"}, + +- {"writePNG", tclGdWriteCmd, 2, 2, 0, 1, ++ {"writeGIF", tclGdWriteCmd, 2, 2, 0, 1, 3, ++ "gdhandle filehandle"}, ++ {"writeJPG", tclGdWriteCmd, 2, 3, 0, 1, 3, ++ "gdhandle filehandle ?quality?"}, ++ {"writeJPEG", tclGdWriteCmd, 2, 3, 0, 1, 3, ++ "gdhandle filehandle ?quality?"}, ++ {"writePNG", tclGdWriteCmd, 2, 2, 0, 1, 3, + "gdhandle filehandle"}, +- {"writePNGvar", tclGdWriteBufCmd, 2, 2, 0, 1, ++ {"writePNGvar", tclGdWriteBufCmd, 2, 2, 0, 1, 0, + "gdhandle var"}, +- {"writeGD", tclGdWriteCmd, 2, 2, 0, 1, ++ {"writeGD", tclGdWriteCmd, 2, 2, 0, 1, 3, + "gdhandle filehandle"}, +- +- {"interlace", tclGdInterlaceCmd, 1, 2, 0, 1, ++ {"writeGD2", tclGdWriteCmd, 2, 2, 0, 1, 3, ++ "gdhandle filehandle"}, ++ {"writeWBMP", tclGdWriteCmd, 3, 3, 0, 1, 3, ++ "gdhandle filehandle foreground"}, ++ {"writeGD2", tclGdWriteCmd, 2, 2, 0, 1, 3, ++ "gdhandle filehandle"}, ++ {"interlace", tclGdInterlaceCmd, 1, 2, 0, 1, 0, + "gdhandle ?on-off?"}, + +- {"color", tclGdColorCmd, 2, 5, 1, 1, ++ {"color", tclGdColorCmd, 2, 5, 1, 1, 0, + "option values..."}, +- {"brush", tclGdBrushCmd, 2, 2, 0, 2, ++ {"brush", tclGdBrushCmd, 2, 2, 0, 2, 0, + "gdhandle brushhandle"}, +- {"style", tclGdStyleCmd, 2, 999, 0, 1, ++ {"style", tclGdStyleCmd, 2, 999, 0, 1, 0, + "gdhandle color..."}, +- {"tile", tclGdTileCmd, 2, 2, 0, 2, ++ {"tile", tclGdTileCmd, 2, 2, 0, 2, 0, + "gdhandle tilehandle"}, + +- {"set", tclGdSetCmd, 4, 4, 0, 1, ++ {"set", tclGdSetCmd, 4, 4, 0, 1, 0, + "gdhandle color x y"}, +- {"line", tclGdLineCmd, 6, 6, 0, 1, ++ {"line", tclGdLineCmd, 6, 6, 0, 1, 0, + "gdhandle color x1 y1 x2 y2"}, +- {"rectangle", tclGdRectCmd, 6, 6, 0, 1, ++ {"rectangle", tclGdRectCmd, 6, 6, 0, 1, 0, + "gdhandle color x1 y1 x2 y2"}, +- {"fillrectangle", tclGdRectCmd, 6, 6, 0, 1, ++ {"fillrectangle", tclGdRectCmd, 6, 6, 0, 1, 0, + "gdhandle color x1 y1 x2 y2"}, +- {"arc", tclGdArcCmd, 8, 8, 0, 1, ++ {"arc", tclGdArcCmd, 8, 8, 0, 1, 0, + "gdhandle color cx cy width height start end"}, +- {"fillarc", tclGdArcCmd, 8, 8, 0, 1, ++ {"fillarc", tclGdArcCmd, 8, 8, 0, 1, 0, + "gdhandle color cx cy width height start end"}, +- {"polygon", tclGdPolygonCmd, 2, 999, 0, 1, ++ {"polygon", tclGdPolygonCmd, 2, 999, 0, 1, 0, + "gdhandle color x1 y1 x2 y2 x3 y3 ..."}, +- {"fillpolygon", tclGdPolygonCmd, 3, 999, 0, 1, ++ {"fillpolygon", tclGdPolygonCmd, 3, 999, 0, 1, 0, + "gdhandle color x1 y1 x2 y2 x3 y3 ..."}, +- {"fill", tclGdFillCmd, 4, 5, 0, 1, ++ {"fill", tclGdFillCmd, 4, 5, 0, 1, 0, + "gdhandle color x y ?bordercolor?"}, + /* +@@ -114,32 +161,25 @@ + * of text string, so the text command provides its own handle processing and checking + */ +- {"text", tclGdTextCmd, 8, 8, 0, 0, ++ {"text", tclGdTextCmd, 8, 8, 0, 0, 4, + "gdhandle color fontpathname size angle x y string"}, + + +- {"copy", tclGdCopyCmd, 8, 10, 0, 2, ++ {"copy", tclGdCopyCmd, 8, 10, 0, 2, 0, + "desthandle srchandle destx desty srcx srcy destw desth ?srcw srch?"}, + +- {"get", tclGdGetCmd, 3, 3, 0, 1, ++ {"get", tclGdGetCmd, 3, 3, 0, 1, 0, + "gdhandle x y"}, +- {"size", tclGdSizeCmd, 1, 1, 0, 1, ++ {"size", tclGdSizeCmd, 1, 1, 0, 1, 0, + "gdhandle"}, + }; + +-static cmdOptions colorCmdVec[] = { +- {"new", tclGdColorNewCmd, 5, 5, 1, 1, +- "gdhandle red green blue"}, +- {"exact", tclGdColorExactCmd, 5, 5, 1, 1, +- "gdhandle red green blue"}, +- {"closest", tclGdColorClosestCmd, 5, 5, 1, 1, +- "gdhandle red green blue"}, +- {"resolve", tclGdColorResolveCmd, 5, 5, 1, 1, +- "gdhandle red green blue"}, +- {"free", tclGdColorFreeCmd, 3, 3, 1, 1, +- "gdhandle color"}, +- {"transparent", tclGdColorTranspCmd, 2, 3, 1, 1, +- "gdhandle ?color?"}, +- {"get", tclGdColorGetCmd, 2, 3, 1, 1, +- "gdhandle ?color?"} ++static cmdImgOptions colorCmdVec[] = { ++ {"new", tclGdColorNewCmd, 5, 5, "red green blue"}, ++ {"exact", tclGdColorExactCmd, 5, 5, "red green blue"}, ++ {"closest", tclGdColorClosestCmd, 5, 5, "red green blue"}, ++ {"resolve", tclGdColorResolveCmd, 5, 5, "red green blue"}, ++ {"free", tclGdColorFreeCmd, 3, 3, "color"}, ++ {"transparent", tclGdColorTranspCmd, 2, 3, "?color?"}, ++ {"get", tclGdColorGetCmd, 2, 3, "?color?"} + }; + +@@ -317,11 +357,10 @@ + * + */ +-int ++static int + gdCmd(ClientData clientData, Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +- GdData *gdData = (GdData *)clientData; +- int argi, subi; +- char buf[100]; ++ unsigned int argi; ++ size_t subi; + /* Check for subcommand. */ + if (argc < 2) { +@@ -336,9 +375,7 @@ + + /* Check arg count. */ +- if (argc - 2 < subcmdVec[subi].minargs || +- argc - 2 > subcmdVec[subi].maxargs) { +- sprintf(buf, "wrong # args: should be \"gd %s %s\"", +- subcmdVec[subi].cmd, subcmdVec[subi].usage); +- Tcl_SetResult(interp, buf, TCL_VOLATILE); ++ if ((unsigned)argc - 2 < subcmdVec[subi].minargs || ++ (unsigned)argc - 2 > subcmdVec[subi].maxargs) { ++ Tcl_WrongNumArgs(interp, 2, objv, subcmdVec[subi].usage); + return TCL_ERROR; + } +@@ -346,20 +383,6 @@ + /* Check for valid handle(s). */ + if (subcmdVec[subi].ishandle > 0) { +- /* Are any handles allocated? */ +- if (gdData->handleTbl == NULL) { +- sprintf(buf, "no such handle%s: ", +- subcmdVec[subi].ishandle > 1 ? "s" : ""); +- Tcl_SetResult(interp, buf, TCL_VOLATILE); +- for (argi = 2 + subcmdVec[subi].subcmds; +- argi < 2 + subcmdVec[subi].subcmds + +- subcmdVec[subi].ishandle; +- argi++) { +- Tcl_AppendResult(interp, +- Tcl_GetString(objv[argi]), " ", 0); +- } +- return TCL_ERROR; +- } + /* Check each handle to see if it's a valid handle. */ +- if (2+subcmdVec[subi].subcmds+subcmdVec[subi].ishandle > argc) { ++ if (2+subcmdVec[subi].subcmds+subcmdVec[subi].ishandle > (unsigned)argc) { + Tcl_SetResult(interp, "GD handle(s) not specified", TCL_STATIC); + return TCL_ERROR; +@@ -369,12 +392,27 @@ + subcmdVec[subi].ishandle); + argi++) { +- if (! gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[argi]))) ++ if (objv[argi]->typePtr != &GdPtrType && ++ GdPtrTypeSet(interp, objv[argi]) != TCL_OK) + return TCL_ERROR; + } + } + ++ /* ++ * If we are operating in a safe interpreter, check, ++ * if this command is suspect -- and only let existing ++ * filehandles through, if so. ++ */ ++ if (clientData != NULL && subcmdVec[subi].unsafearg != 0) { ++ const char *fname = ++ Tcl_GetString(objv[subcmdVec[subi].unsafearg]); ++ if (!Tcl_IsChannelExisting(fname)) { ++ Tcl_AppendResult(interp, "Access to ", fname, ++ " not allowed in safe interpreter", TCL_STATIC); ++ return TCL_ERROR; ++ } ++ } ++ + /* Call the subcommand function. */ +- return (*subcmdVec[subi].f)(interp, gdData, argc, objv); ++ return (*subcmdVec[subi].f)(interp, argc, objv); + } + } +@@ -390,5 +427,5 @@ + + static int +-tclGdCreateCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdCreateCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -397,16 +434,29 @@ + FILE *filePtr; + ClientData clientdata; +- char *cmd, buf[50]; ++ char *cmd; ++ Tcl_Obj *result; + int fileByName; + + cmd = Tcl_GetString(objv[1]); + if (strcmp(cmd, "create") == 0) { ++ int trueColor = 0; ++ + if (Tcl_GetIntFromObj(interp, objv[2], &w) != TCL_OK) + return TCL_ERROR; + if (Tcl_GetIntFromObj(interp, objv[3], &h) != TCL_OK) + return TCL_ERROR; ++ /* An optional argument may specify true for "TrueColor" */ ++ if (argc == 5 && Tcl_GetBooleanFromObj(interp, objv[4], ++ &trueColor) == TCL_ERROR) ++ return TCL_ERROR; ++ ++ if (trueColor) ++ im = gdImageCreateTrueColor(w, h); ++ else + im = gdImageCreate(w, h); ++ + if (im == NULL) + { ++ char buf[255]; + sprintf(buf, "GD unable to allocate %d X %d image", w, h); + Tcl_SetResult(interp, buf, TCL_VOLATILE); +@@ -414,6 +464,19 @@ + } + } else { ++ char *arg2 = Tcl_GetString(objv[2]); + fileByName = 0; /* first try to get file from open channel */ +- if (Tcl_GetOpenFile(interp, Tcl_GetString(objv[2]), 0, 1, &clientdata) == TCL_OK) { ++ ++ if (cmd[10] == 'X' && cmd[11] == 'P' && cmd[12] == 'M') { ++#ifdef NOX11 ++ Tcl_SetResult(interp, "Support for XPM-files not " ++ "compiled in", TCL_STATIC); ++ return TCL_ERROR; ++#else ++ /* gdImageCreateFromXpm() takes fileNAME */ ++ im = gdImageCreateFromXpm(arg2); ++#endif ++ } else { ++ if (Tcl_GetOpenFile(interp, arg2, 0, 1, &clientdata) ++ == TCL_OK) { + filePtr = (FILE *)clientdata; + } else { +@@ -422,43 +485,68 @@ + */ + fileByName++; +- if ((filePtr = fopen(Tcl_GetString(objv[2]),"rb")) == NULL) { ++ if ((filePtr = fopen(arg2, "rb")) == NULL) { ++ Tcl_AppendResult(interp, ++ "could not open :", arg2, "': ", ++ strerror(errno), NULL); + return TCL_ERROR; + } + Tcl_ResetResult(interp); + } ++ + /* Read PNG, XBM, or GD file? */ +- if (cmd[10] == 'P') { ++ switch (cmd[10]) { ++ case 'P': + im = gdImageCreateFromPng(filePtr); +- } else if (cmd[10] == 'X') { ++ break; ++ case 'X': + im = gdImageCreateFromXbm(filePtr); +- } else { ++ break; ++ case 'G': /* GIF, GD2, and GD */ ++ if (cmd[11] == 'I') ++ im = gdImageCreateFromGif(filePtr); ++ else if (cmd[12] == '2') ++ im = gdImageCreateFromGd2(filePtr); ++ else + im = gdImageCreateFromGd(filePtr); ++ break; ++ case 'J': ++ im = gdImageCreateFromJpeg(filePtr); ++ break; ++ case 'W': ++ im = gdImageCreateFromWBMP(filePtr); ++ break; ++ default: ++ Tcl_AppendResult(interp, cmd + 10, ++ "unrecognizable format requested", NULL); ++ return TCL_ERROR; + } + if (fileByName) { + fclose(filePtr); + } ++ } ++ + if (im == NULL) { +- Tcl_SetResult(interp,"GD unable to read image file", TCL_STATIC); ++ Tcl_AppendResult(interp, ++ "GD unable to read image file `", arg2, "' as ", ++ cmd + 10, NULL); + return TCL_ERROR; + } + } + +- *(gdImagePtr *)(gdHandleAlloc(gdData->handleTbl, buf)) = im; +- Tcl_SetResult(interp, buf, TCL_VOLATILE); ++ result = Tcl_NewObj(); ++ IMGPTR(result) = im; ++ result->typePtr = &GdPtrType; ++ result->bytes = NULL; ++ Tcl_SetObjResult(interp, result); + return TCL_OK; + } + + static int +-tclGdDestroyCmd(Tcl_Interp *interp, GdData *gdData, int argc, Tcl_Obj *CONST objv[]) ++tclGdDestroyCmd(Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]) + { + gdImagePtr im; +- void *hdl; + +- /* Get the handle, and the image pointer. */ +- hdl = (void *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); +- im = *(gdImagePtr *)hdl; +- /* Release the handle, destroy the image. */ +- gdHandleFree(gdData->handleTbl, hdl); ++ /* Get the image pointer and destroy it */ ++ im = IMGPTR(objv[2]); + gdImageDestroy(im); + +@@ -467,20 +555,45 @@ + + static int +-tclGdWriteCmd(Tcl_Interp *interp, GdData *gdData, int argc, Tcl_Obj *CONST objv[]) ++tclGdWriteCmd(Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]) + { + gdImagePtr im; + FILE *filePtr; + ClientData clientdata; +- char *cmd; ++ const char *cmd, *fname; + int fileByName; ++ int arg4; + + cmd = Tcl_GetString(objv[1]); ++ if (cmd[5] == 'J' || cmd[5] == 'W') { ++ /* JPEG and WBMP expect an extra (integer) argument */ ++ if (argc < 5) { ++ if (cmd[5] == 'J') ++ arg4 = -1; /* default quality-level */ ++ else { ++ Tcl_SetResult(interp, "WBMP saving requires" ++ " the foreground pixel value", TCL_STATIC); ++ return TCL_ERROR; ++ } ++ } else if (Tcl_GetIntFromObj(interp, objv[4], &arg4) != TCL_OK) ++ return TCL_ERROR; ++ ++ if (cmd[5] == 'J' && argc > 4 && (arg4 > 100 || arg4 < 1)) { ++ Tcl_SetObjResult(interp, objv[4]); ++ Tcl_AppendResult(interp, ": JPEG image quality, if " ++ "specified, must be an integer from 1 to 100, " ++ "or -1 for default", NULL); ++ return TCL_ERROR; ++ } ++ /* XXX no error-checking for the WBMP case here */ ++ } ++ + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); ++ ++ fname = Tcl_GetString(objv[3]); + + /* Get the file reference. */ + fileByName = 0; /* first try to get file from open channel */ +- if (Tcl_GetOpenFile(interp, Tcl_GetString(objv[3]), 1, 1, &clientdata) == TCL_OK) { ++ if (Tcl_GetOpenFile(interp, fname, 1, 1, &clientdata) == TCL_OK) { + filePtr = (FILE *)clientdata; + } else { +@@ -489,5 +602,7 @@ + */ + fileByName++; +- if ((filePtr = fopen(Tcl_GetString(objv[3]),"wb")) == NULL) { ++ if ((filePtr = fopen(fname, "wb")) == NULL) { ++ Tcl_AppendResult(interp, "could not open :", fname, ++ "': ", strerror(errno), NULL); + return TCL_ERROR; + } +@@ -496,8 +611,22 @@ + + /* Do it. */ +- if (cmd[5] == 'P') { ++ switch (cmd[5]) { ++ case 'P': + gdImagePng(im, filePtr); +- } else { ++ break; ++ case 'G': ++ if (cmd[6] == 'I') ++ gdImageGif(im, filePtr); ++ else if (cmd[7] == '2') ++ gdImageGd2(im, filePtr, GD2_CHUNKSIZE, GD2_FMT_COMPRESSED); ++ else + gdImageGd(im, filePtr); ++ break; ++ case 'J': ++ gdImageJpeg(im, filePtr, arg4); ++ break; ++ case 'B': ++ gdImageWBMP(im, arg4, filePtr); ++ break; + } + if (fileByName) { +@@ -510,5 +639,5 @@ + + static int +-tclGdInterlaceCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdInterlaceCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -517,6 +646,5 @@ + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + if (argc == 4) { +@@ -535,7 +663,6 @@ + } + +- + static int +-tclGdColorCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdColorCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -551,17 +678,14 @@ + { + /* Check arg count. */ +- if (argc - 2 < colorCmdVec[subi].minargs || +- argc - 2 > colorCmdVec[subi].maxargs) ++ if ((unsigned)argc - 2 < colorCmdVec[subi].minargs || ++ (unsigned)argc - 2 > colorCmdVec[subi].maxargs) + { +- Tcl_AppendResult(interp, +- "wrong # args: should be \"gd color ", +- colorCmdVec[subi].cmd, " ", +- colorCmdVec[subi].usage, "\"", 0); ++ Tcl_WrongNumArgs(interp, 3, objv, ++ colorCmdVec[subi].usage); + return TCL_ERROR; + } + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[3])); ++ im = IMGPTR(objv[3]); + /* Parse off integer arguments. + * 1st 4 are gd color <opt> <handle> +@@ -605,5 +729,5 @@ + + static int +-tclGdColorNewCmd(Tcl_Interp *interp, gdImagePtr im, int argc, int args[]) ++tclGdColorNewCmd(Tcl_Interp *interp, gdImagePtr im, int argc, const int args[]) + { + int color; +@@ -615,5 +739,5 @@ + + static int +-tclGdColorExactCmd(Tcl_Interp *interp, gdImagePtr im, int argc, int args[]) ++tclGdColorExactCmd(Tcl_Interp *interp, gdImagePtr im, int argc, const int args[]) + { + int color; +@@ -625,5 +749,5 @@ + + static int +-tclGdColorClosestCmd(Tcl_Interp *interp, gdImagePtr im, int argc, int args[]) ++tclGdColorClosestCmd(Tcl_Interp *interp, gdImagePtr im, int argc, const int args[]) + { + int color; +@@ -635,5 +759,5 @@ + + static int +-tclGdColorResolveCmd(Tcl_Interp *interp, gdImagePtr im, int argc, int args[]) ++tclGdColorResolveCmd(Tcl_Interp *interp, gdImagePtr im, int argc, const int args[]) + { + int color; +@@ -645,5 +769,5 @@ + + static int +-tclGdColorFreeCmd(Tcl_Interp *interp, gdImagePtr im, int argc, int args[]) ++tclGdColorFreeCmd(Tcl_Interp *interp, gdImagePtr im, int argc, const int args[]) + { + gdImageColorDeallocate(im, args[0]); +@@ -652,5 +776,5 @@ + + static int +-tclGdColorTranspCmd(Tcl_Interp *interp, gdImagePtr im, int argc, int args[]) ++tclGdColorTranspCmd(Tcl_Interp *interp, gdImagePtr im, int argc, const int args[]) + { + int color; +@@ -668,33 +792,37 @@ + + static int +-tclGdColorGetCmd(Tcl_Interp *interp, gdImagePtr im, int argc, int args[]) ++tclGdColorGetCmd(Tcl_Interp *interp, gdImagePtr im, int argc, const int args[]) + { +- char buf[30]; +- int i; ++ int i, ncolors; ++ Tcl_Obj *tuple[4], *result; + ++ ncolors = gdImageColorsTotal(im); + /* IF one arg, return the single color, else return list of all colors. */ + if (argc == 1) + { + i = args[0]; +- if (i >= gdImageColorsTotal(im) || im->open[i]) { ++ if (i >= ncolors || im->open[i]) { + Tcl_SetResult(interp, "No such color", TCL_STATIC); + return TCL_ERROR; + } +- sprintf(buf, "%d %d %d %d", i, +- gdImageRed(im,i), +- gdImageGreen(im,i), +- gdImageBlue(im,i)); +- Tcl_SetResult(interp, buf, TCL_VOLATILE); ++ tuple[0] = Tcl_NewIntObj(i); ++ tuple[1] = Tcl_NewIntObj(gdImageRed(im,i)); ++ tuple[2] = Tcl_NewIntObj(gdImageGreen(im,i)); ++ tuple[3] = Tcl_NewIntObj(gdImageBlue(im,i)); ++ Tcl_SetObjResult(interp, Tcl_NewListObj(4, tuple)); + } else { +- for (i = 0; i < gdImageColorsTotal(im); i++) ++ result = Tcl_NewListObj(0, NULL); ++ for (i = 0; i < ncolors; i++) + { + if (im->open[i]) + continue; +- sprintf(buf, "%d %d %d %d", i, +- gdImageRed(im,i), +- gdImageGreen(im,i), +- gdImageBlue(im,i)); +- Tcl_AppendElement(interp, buf); ++ tuple[0] = Tcl_NewIntObj(i); ++ tuple[1] = Tcl_NewIntObj(gdImageRed(im,i)); ++ tuple[2] = Tcl_NewIntObj(gdImageGreen(im,i)); ++ tuple[3] = Tcl_NewIntObj(gdImageBlue(im,i)); ++ Tcl_ListObjAppendElement(NULL, result, ++ Tcl_NewListObj(4, tuple)); + } ++ Tcl_SetObjResult(interp, result); + } + +@@ -703,5 +831,5 @@ + + static int +-tclGdBrushCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdBrushCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -709,8 +837,6 @@ + + /* Get the image pointers. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); +- imbrush = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[3])); ++ im = IMGPTR(objv[2]); ++ imbrush = IMGPTR(objv[3]); + + /* Do it. */ +@@ -721,5 +847,5 @@ + + static int +-tclGdTileCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdTileCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -727,8 +853,6 @@ + + /* Get the image pointers. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); +- tile = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[3])); ++ im = IMGPTR(objv[2]); ++ tile = IMGPTR(objv[3]); + + /* Do it. */ +@@ -740,5 +864,5 @@ + + static int +-tclGdStyleCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdStyleCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -749,6 +873,5 @@ + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + /* Figure out how many colors in the style list and allocate memory. */ +@@ -788,5 +911,5 @@ + + static int +-tclGdSetCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdSetCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -795,6 +918,5 @@ + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + /* Get the color, x, y values. */ +@@ -813,5 +935,5 @@ + + static int +-tclGdLineCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdLineCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -820,6 +942,5 @@ + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + /* Get the color, x, y values. */ +@@ -842,14 +963,13 @@ + + static int +-tclGdRectCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdRectCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { + gdImagePtr im; + int color, x1, y1, x2, y2; +- char *cmd; ++ const char *cmd; + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + /* Get the color, x, y values. */ +@@ -876,14 +996,13 @@ + + static int +-tclGdArcCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdArcCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { + gdImagePtr im; + int color, cx, cy, width, height, start, end; +- char *cmd; ++ const char *cmd; + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + /* Get the color, x, y values. */ +@@ -917,5 +1036,5 @@ + + static int +-tclGdPolygonCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdPolygonCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -925,9 +1044,8 @@ + gdPointPtr points = NULL; + int retval = TCL_OK; +- char *cmd; ++ const char *cmd; + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + /* Get the color, x, y values. */ +@@ -974,5 +1092,5 @@ + { + retval = TCL_ERROR; +- break; ++ goto out; + } + +@@ -989,9 +1107,9 @@ + Tcl_Free((char *)points); + +- return TCL_OK; ++ return retval; + } + + static int +-tclGdFillCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdFillCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -1000,6 +1118,5 @@ + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + /* Get the color, x, y and possibly bordercolor values. */ +@@ -1024,5 +1141,5 @@ + + static int +-tclGdCopyCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdCopyCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -1031,8 +1148,6 @@ + + /* Get the image pointer. */ +- imdest = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); +- imsrc = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[3])); ++ imdest = IMGPTR(objv[2]); ++ imsrc = IMGPTR(objv[3]); + + /* Get the x, y, etc. values. */ +@@ -1067,5 +1182,5 @@ + + static int +-tclGdGetCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdGetCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -1074,6 +1189,5 @@ + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + /* Get the x, y values. */ +@@ -1090,21 +1204,21 @@ + + static int +-tclGdSizeCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdSizeCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { + gdImagePtr im; +- char buf[30]; ++ Tcl_Obj *answers[2]; + + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + +- sprintf(buf, "%d %d", gdImageSX(im), gdImageSY(im)); +- Tcl_SetResult(interp, buf, TCL_VOLATILE); ++ answers[0] = Tcl_NewIntObj(gdImageSX(im)); ++ answers[1] = Tcl_NewIntObj(gdImageSY(im)); ++ Tcl_SetObjResult(interp, Tcl_NewListObj(2, answers)); + return TCL_OK; + } + + static int +-tclGdTextCmd(Tcl_Interp *interp, GdData *gdData, ++tclGdTextCmd(Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]) + { +@@ -1113,16 +1227,17 @@ + int color, x, y; + double ptsize, angle; +- char *error, buf[32], *font, *handle; ++ char *error, *font; + int i, brect[8], len; + unsigned char *str; ++ Tcl_Obj *orect[8]; + + /* Get the image pointer. (an invalid or null arg[2] will result in string + size calculation but no rendering */ +- handle = Tcl_GetString(objv[2]); +- if (! handle || *handle == '\0') { +- im = (gdImagePtr)NULL; ++ if (argc == 2 || (objv[2]->typePtr != &GdPtrType && ++ GdPtrTypeSet(NULL, objv[2]) != TCL_OK)) { ++ im = NULL; + } + else { +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, handle); ++ im = IMGPTR(objv[2]); + } + +@@ -1159,8 +1274,8 @@ + return TCL_ERROR; + } +- for (i=0; i<8; i++) { +- sprintf(buf, "%d", brect[i]); +- Tcl_AppendElement(interp, buf); +- } ++ for (i=0; i<8; i++) ++ orect[i] = Tcl_NewIntObj(brect[i]); ++ ++ Tcl_SetObjResult(interp, Tcl_NewListObj(8, orect)); + return TCL_OK; + } +@@ -1176,6 +1291,4 @@ + #endif + { +- static GdData gdData; +- + #ifdef USE_TCL_STUBS + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { +@@ -1183,5 +1296,5 @@ + } + #else +- if (Tcl_PkgRequired(interp, "Tcl", TCL_VERSION, 0) == NULL) { ++ if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } +@@ -1191,11 +1304,5 @@ + } + +- GDHandleTable = gdData.handleTbl = gdHandleTblInit("gd", sizeof(gdImagePtr), 1); +- if (gdData.handleTbl == NULL) { +- Tcl_AppendResult(interp, "unable to create table for GD handles.", 0); +- return TCL_ERROR; +- } +- +- Tcl_CreateObjCommand(interp, "gd", gdCmd, (ClientData)&gdData, (Tcl_CmdDeleteProc *)NULL); ++ Tcl_CreateObjCommand(interp, "gd", gdCmd, NULL, (Tcl_CmdDeleteProc *)NULL); + return TCL_OK; + } +@@ -1207,5 +1314,12 @@ + #endif + { +- return Gdtclft_Init(interp); ++ Tcl_CmdInfo info; ++ if (Gdtclft_Init(interp) != TCL_OK || ++ Tcl_GetCommandInfo(interp, "gd", &info) != 1) ++ return TCL_ERROR; ++ info.objClientData = (char *)info.objClientData + 1; /* Non-NULL */ ++ if (Tcl_SetCommandInfo(interp, "gd", &info) != 1) ++ return TCL_ERROR; ++ return TCL_OK; + } + +@@ -1264,9 +1378,8 @@ + + static int +-tclGdWriteBufCmd(Tcl_Interp *interp, GdData *gdData, int argc, Tcl_Obj *CONST objv[]) ++tclGdWriteBufCmd(Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]) + { + gdImagePtr im; + Tcl_Obj *output; +- char *cmd; + char *result = NULL; + +@@ -1282,8 +1395,6 @@ + }; + +- cmd = Tcl_GetString(objv[1]); + /* Get the image pointer. */ +- im = *(gdImagePtr *)gdHandleXlate(interp, gdData->handleTbl, +- Tcl_GetString(objv[2])); ++ im = IMGPTR(objv[2]); + + gdImagePngToSink(im, &buffsink); +@@ -1305,2 +1416,26 @@ + return TCL_OK; + } ++ ++static void ++GdPtrTypeUpdate(struct Tcl_Obj *O) ++{ ++ O->bytes = Tcl_Alloc(strlen(GdPtrType.name) + ++ (sizeof(void *) + 1) * 2 + 1); ++ O->length = sprintf(O->bytes, "%s%p", GdPtrType.name, IMGPTR(O)); ++} ++ ++static int ++GdPtrTypeSet(Tcl_Interp *I, struct Tcl_Obj *O) ++{ ++ if (O->bytes == NULL || O->bytes[0] == '\0' || ++ strncmp(GdPtrType.name, O->bytes, strlen(GdPtrType.name)) != 0 || ++ sscanf(O->bytes + strlen(GdPtrType.name), "%p", &IMGPTR(O)) != 1) { ++ if (I != NULL) ++ Tcl_AppendResult(I, O->bytes, " is not a ", ++ GdPtrType.name, "-handle", NULL); ++ return TCL_ERROR; ++ } ++ ++ O->typePtr = &GdPtrType; ++ return TCL_OK; ++} +--- gdtclft.n Fri Aug 4 17:11:41 2000 ++++ gdtclft.n Mon Dec 4 03:52:10 2006 +@@ -9,98 +9,89 @@ + + TCL GD EXTENSION +- ++ + Thomas Boutell's Gd package provides a convenient way to generate + PNG images with a C program. If you, like me, prefer Tcl for CGI +- applications, you'll want my TCL GD extension. You can get it by +- anonymous FTP from ftp://guraldi.hgp.med.umich.edu/pub/gdtcl.shar. +- +- Here's a quick overview of the package. +- * Overview +- * Installation +- * Reference +- * Examples +- + gdsample -- sample program written in Tcl. +- + Gddemo -- demo program written in Tcl. +- + gdshow -- procedure to display an image. +- ++ applications, you'll want my TCL GD extension. ++ + A TCL INTERFACE TO THE GD PACKAGE +- ++ + Spencer W. Thomas + Human Genome Center + University of Michigan + Ann Arbor, MI 48109 +- ++ + spencer.thomas@med.umich.edu + + TrueType font support using the FreeType library was added by +- John Ellson (ellson@graphviz.org) ++ John Ellson (ellson@graphviz.org). + +- Latest sources available from: ++ FreeBSD port maintained by Mikhail Teterin (mi@aldan.algebra.com). + +- http://www.graphviz.org/pub/ +- +- + Overview + + This package provides a simple Tcl interface to the gd (PNG drawing) +- package, version 1.1. It includes an interface to all the gd functions ++ package. It includes an interface to most of the gd functions + and data structures from Tcl commands. +- +- +- +-Installation +- +- ./configure +- make +- make install +- ++ ++ + Reference + + One Tcl command, 'gd', is added. All gd package actions are + sub-commands (or "options" in Tcl terminology) of this command. +- ++ + Each active gd image is referred to with a "handle". The handle is a + name of the form gd# (e.g., gd0) returned by the gd create options. +- ++ + Almost all the gd commands take a handle as the first argument (after + the option). All the drawing commands take a color_idx as the next + argument. +- ++ +- gd create <width> <height> ++ gd create <width> <height> ?true? + Return a handle to a new gdImage that is width X height. ++ If "true" is specified, the new image is "TrueColor". +- +- gd createFromPNG <filehandle> +- +- gd createFromGD <filehandle> +- +- gd createFromXBM <filehandle> ++ ++ gd createFromGD <file> ++ gd createFromGD2 <file> ++ gd createFromGIF <file> ++ gd createFromJPG <file> ++ gd createFromPNG <file> ++ gd createFromWBMP <file> ++ gd createFromXBM <file> ++ gd createFromXPM <filename> ++ + Return a handle to a new gdImage created by reading a PNG +- (resp. GD or XBM) image from the file open on filehandle. +- ++ (resp. GD or XBM) image from the <file>, which is either ++ a TCl filehandle, or a filename (except for XPM, which only ++ accepts filenames). ++ + gd destroy <gdhandle> + Destroy the gdImage referred to by gdhandle. +- +- gd writePNG <gdhandle> <filehandle> +- +- gd writeGD <gdhandle> <filehandle> +- Write the image in gdhandle to filehandle as a PNG (resp. GD) +- file. ++ ++ gd writeGD <gdhandle> <file> ++ gd writeGD2 <gdhandle> <file> ++ gd writeGIF <gdhandle> <file> ++ gd writeJPG <gdhandle> <file> ?quality? ++ gd writePNG <gdhandle> <file> ++ gd writeWBMP <gdhandle> <file> fgpixel ++ ++ Write the image in gdhandle to <file> (filehandle or filename) ++ in one of the specified formats. + + gd writePNGvar <gdhandle> <varname> + Write the image in gdhandle to Tcl variable "varname" as a binary + coded PNG object. +- ++ + gd interlace <gdhandle> <on-off> + Make the output image interlaced (if on-off is true) or not (if + on-off is false). +- ++ + gd color new <gdhandle> <red> <green> <blue> + Allocate a new color with the given RGB values. Returns the + color_idx, or -1 on failure (256 colors already allocated). +- ++ + gd color exact <gdhandle> <red> <green> <blue> +- Find a color_idx in the image that exactly matches the given RGB ++ Find a color_idx in the image that exactly matches the given RGB + color. Returns the color_idx, or -1 if no exact match. +- ++ + gd color closest <gdhandle> <red> <green> <blue> + Find a color in the image that is closest to the given RGB color. +@@ -114,23 +104,23 @@ + set idx [gd color closest $gd $r $g $b] + } +- } +- ++ } ++ + gd color free <gdhandle> <color_idx> + Free the color at the given color_idx for reuse. +- ++ + gd color transparent <gdhandle> [<color_idx>] + Mark the color at <color_idx> as the transparent background color. Or, + return the transparent color_idx if no color_idx specified. +- ++ + gd color get <gdhandle> [<color_idx>] + Return the RGB value at <color_idx>, or {} if it is not allocated. + If <color_idx> is not specified, return a list of {color_idx R G B} + values for all allocated colors. +- ++ + gd brush <gdhandle> <brushhandle> + Set the brush image to be used for brushed lines. Transparent + pixels in the brush will not change the image when the brush is + applied. +- ++ + gd style <gdhandle> <color_idx> ... + Set the line style to the list of color indices. This is +@@ -141,10 +131,10 @@ + means not to fill the pixel, and a non-zero value means to + apply the brush. +- ++ + gd tile <gdhandle> <tilehandle> + Set the tile image to be used for tiled fills. Transparent + pixels in the tile will not change the underlying image during + tiling. +- ++ + In all drawing functions, the color_idx is a number, or may + be one of the strings styled, brushed, tiled, "styled brushed" +@@ -152,56 +142,55 @@ + effect will be used. Brushing and styling apply to lines, + tiling to filled areas. +- ++ + gd set <gdhandle> <color_idx> <x> <y> + Set the pixel at (x,y) to color <color_idx>. +- ++ + gd line <gdhandle> <color_idx> <x1> <y1> <x2> <y2> +- ++ + gd rectangle <gdhandle> <color_idx> <x1> <y1> <x2> <y2> +- ++ + gd fillrectangle <gdhandle> <color_idx> <x1> <y1> <x2> <y2> + Draw the outline of (resp. fill) a rectangle in color <color_idx> + with corners at (x1,y1) and (x2,y2). +- ++ + gd arc <gdhandle> <color_idx> <cx> <cy> <width> <height> <start> <end> + Draw an arc in color <color_idx>, centered at (cx,cy) in a rectangle width + x height, starting at start degrees and ending at end degrees. + start must be > end. +- ++ + gd polygon <gdhandle> <color_idx> <x1> <y1> ... +- ++ + gd fillpolygon <gdhandle> <color_idx> <x1> <y1> ... + Draw the outline of, or fill, a polygon specified by the x, y + coordinate list. There must be at least 3 points specified. +- ++ + gd fill <gdhandle> <color_idx> <x> <y> +- ++ + gd fill <gdhandle> <color_idx> <x> <y> <borderindex> + Fill with color <color_idx>, starting from (x,y) within a region of + pixels all the color of the pixel at (x,y) (resp., within a + border colored borderindex). +- ++ + gd size <gdhandle> + Returns a list {width height} of the image. +- +- gd text <gdhandle> <color_idx> <fontpath> <size> <angle> <x> <y> <string> +- Draw text using the .ttf font in <fontpath> in color <color_idx>, +- with pointsize <size>, rotation in radians <angle>, with lower left ++ ++ gd text <gdhandle> <color_idx> <fontpath> <size> <angle> <x> <y> <string> ++ Draw text using the .ttf font in <fontpath> in color <color_idx>, ++ with pointsize <size>, rotation in radians <angle>, with lower left + corner at (x,y). String may contain UTF8 sequences like: "À" + Returns 4 corner coords of bounding rectangle. + Use gdhandle = {} to get boundary without rendering. + Use negative of color_idx to disable antialiasing. +- ++ + gd copy <desthandle> <srchandle> <destx> <desty> <srcx> <srcy> <w> <h> +- +- gd copy <desthandle> <srchandle> <destx> <desty> <srcx> <srcy> \ +- <destw> <desth> <srcw> <srch> Copy a subimage from +- srchandle(srcx, srcy) to desthandle(destx, desty), size w x h. ++ ++ gd copy <desthandle> <srchandle> <destx> <desty> <srcx> <srcy> \\ ++ <destw> <desth> <srcw> <srch> ++ Copy a subimage from srchandle(srcx, srcy) to desthandle(destx, ++ desty), size w x h. + Or, resize the subimage in copying from srcw x srch to destw x + desth. +- +- +- +-Examples ++ ++.SH EXAMPLES + + The sample program from the gd documentation can be written thusly: +@@ -234,8 +223,8 @@ + gd destroy $im + +- +- ++ ++ + GDDEMO +- ++ + Here's the gddemo.c program translated to tcl. + +@@ -312,8 +301,8 @@ + gd destroy $im_out + +- +- ++ ++ + GDSHOW +- ++ + A quick Tcl procedure to display a GD image using the xv program. + +@@ -331,2 +320,6 @@ + } + } ++ ++.SH SEE ALSO ++ You will find Thomas Boutell's documentation for the underlying GD ++ library quite useful, especially, if you are dealing with WBMP format. +--- gdhandle.c 2000-02-11 00:24:31.000000000 -0500 ++++ gdhandle.c 2014-04-29 13:25:00.000000000 -0400 +@@ -45,5 +45,5 @@ + * It is set on the first table initialization. + */ +-static int entryAlignment = 0; ++static size_t entryAlignment = 0; + + /* diff --git a/graphics/gdtclft/pkg-descr b/graphics/gdtclft/pkg-descr new file mode 100644 index 000000000000..ea18fed48fdf --- /dev/null +++ b/graphics/gdtclft/pkg-descr @@ -0,0 +1,10 @@ +Spencer Thomas said about the original TCL GD: + + Thomas Boutell's Gd package provides a convenient way to + generate PNG images with a C program. If you, like me, prefer + Tcl for CGI applications, you'll want my TCL GD extension. + +The software is now maintained by John Ellson <ellson@lucent.com>, it +seems. + +WWW: http://graphviz.org/cgi-bin/man?gdtclft |