diff options
Diffstat (limited to 'generic/tkCanvImg.c')
-rw-r--r-- | generic/tkCanvImg.c | 290 |
1 files changed, 255 insertions, 35 deletions
diff --git a/generic/tkCanvImg.c b/generic/tkCanvImg.c index cf1106d..144b755 100644 --- a/generic/tkCanvImg.c +++ b/generic/tkCanvImg.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCanvImg.c,v 1.3 1999/04/16 01:51:11 stanton Exp $ + * RCS: @(#) $Id: tkCanvImg.c,v 1.4 1999/12/14 06:52:25 hobbs Exp $ */ #include <stdio.h> @@ -31,23 +31,45 @@ typedef struct ImageItem { * (x,y). */ char *imageString; /* String describing -image option (malloc-ed). * NULL means no image right now. */ + char *activeImageString; /* String describing -activeimage option. + * NULL means no image right now. */ + char *disabledImageString; /* String describing -disabledimage option. + * NULL means no image right now. */ Tk_Image image; /* Image to display in window, or NULL if * no image at present. */ + Tk_Image activeImage; /* Image to display in window, or NULL if + * no image at present. */ + Tk_Image disabledImage; /* Image to display in window, or NULL if + * no image at present. */ } ImageItem; /* * Information used for parsing configuration specs: */ -static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc, +static Tk_CustomOption stateOption = { + (Tk_OptionParseProc *) TkStateParseProc, + TkStatePrintProc, (ClientData) 2 +}; +static Tk_CustomOption tagsOption = { + (Tk_OptionParseProc *) Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, (ClientData) NULL }; static Tk_ConfigSpec configSpecs[] = { + {TK_CONFIG_STRING, "-activeimage", (char *) NULL, (char *) NULL, + (char *) NULL, Tk_Offset(ImageItem, activeImageString), + TK_CONFIG_NULL_OK}, {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL, "center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT}, + {TK_CONFIG_STRING, "-disabledimage", (char *) NULL, (char *) NULL, + (char *) NULL, Tk_Offset(ImageItem, disabledImageString), + TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, + (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, + &stateOption}, {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, @@ -63,19 +85,21 @@ static void ImageChangedProc _ANSI_ARGS_((ClientData clientData, int imgHeight)); static int ImageCoords _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - char **argv)); + Tcl_Obj *CONST argv[])); static int ImageToArea _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double *rectPtr)); static double ImageToPoint _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double *coordPtr)); +static int ImageToPostscript _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); static void ComputeImageBbox _ANSI_ARGS_((Tk_Canvas canvas, ImageItem *imgPtr)); static int ConfigureImage _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - char **argv, int flags)); + Tcl_Obj *CONST argv[], int flags)); static int CreateImage _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int argc, char **argv)); + int argc, Tcl_Obj *CONST argv[])); static void DeleteImage _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, Display *display)); static void DisplayImage _ANSI_ARGS_((Tk_Canvas canvas, @@ -101,10 +125,10 @@ Tk_ItemType tkImageType = { ImageCoords, /* coordProc */ DeleteImage, /* deleteProc */ DisplayImage, /* displayProc */ - 0, /* alwaysRedraw */ + TK_CONFIG_OBJS, /* flags */ ImageToPoint, /* pointProc */ ImageToArea, /* areaProc */ - (Tk_ItemPostscriptProc *) NULL, /* postscriptProc */ + ImageToPostscript, /* postscriptProc */ ScaleImage, /* scaleProc */ TranslateImage, /* translateProc */ (Tk_ItemIndexProc *) NULL, /* indexProc */ @@ -112,7 +136,7 @@ Tk_ItemType tkImageType = { (Tk_ItemSelectionProc *) NULL, /* selectionProc */ (Tk_ItemInsertProc *) NULL, /* insertProc */ (Tk_ItemDCharsProc *) NULL, /* dTextProc */ - (Tk_ItemType *) NULL /* nextPtr */ + (Tk_ItemType *) NULL, /* nextPtr */ }; /* @@ -142,11 +166,24 @@ CreateImage(interp, canvas, itemPtr, argc, argv) Tk_Item *itemPtr; /* Record to hold new item; header * has been initialized by caller. */ int argc; /* Number of arguments in argv. */ - char **argv; /* Arguments describing rectangle. */ + Tcl_Obj *CONST argv[]; /* Arguments describing rectangle. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; + int i; - if (argc < 2) { + if (argc==1) { + i = 1; + } else { + char *arg = Tcl_GetStringFromObj((Tcl_Obj *) argv[1], NULL); + if (((argc>1) && (arg[0] == '-') + && (arg[1] >= 'a') && (arg[1] <= 'z'))) { + i = 1; + } else { + i = 2; + } + } + + if (argc < i) { Tcl_AppendResult(interp, "wrong # args: should be \"", Tk_PathName(Tk_CanvasTkwin(canvas)), " create ", itemPtr->typePtr->name, " x y ?options?\"", @@ -161,23 +198,26 @@ CreateImage(interp, canvas, itemPtr, argc, argv) imgPtr->canvas = canvas; imgPtr->anchor = TK_ANCHOR_CENTER; imgPtr->imageString = NULL; + imgPtr->activeImageString = NULL; + imgPtr->disabledImageString = NULL; imgPtr->image = NULL; + imgPtr->activeImage = NULL; + imgPtr->disabledImage = NULL; /* * Process the arguments to fill in the item record. */ - if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &imgPtr->x) != TCL_OK) - || (Tk_CanvasGetCoord(interp, canvas, argv[1], &imgPtr->y) - != TCL_OK)) { - return TCL_ERROR; + if ((ImageCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) { + goto error; } - - if (ConfigureImage(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) { - DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); - return TCL_ERROR; + if (ConfigureImage(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) { + return TCL_OK; } - return TCL_OK; + + error: + DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); + return TCL_ERROR; } /* @@ -206,20 +246,34 @@ ImageCoords(interp, canvas, itemPtr, argc, argv) * read or modified. */ int argc; /* Number of coordinates supplied in * argv. */ - char **argv; /* Array of coordinates: x1, y1, + Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1, * x2, y2, ... */ { ImageItem *imgPtr = (ImageItem *) itemPtr; - char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE]; if (argc == 0) { - Tcl_PrintDouble(interp, imgPtr->x, x); - Tcl_PrintDouble(interp, imgPtr->y, y); - Tcl_AppendResult(interp, x, " ", y, (char *) NULL); - } else if (argc == 2) { - if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &imgPtr->x) != TCL_OK) - || (Tk_CanvasGetCoord(interp, canvas, argv[1], - &imgPtr->y) != TCL_OK)) { + Tcl_Obj *obj = Tcl_NewObj(); + Tcl_Obj *subobj = Tcl_NewDoubleObj(imgPtr->x); + Tcl_ListObjAppendElement(interp, obj, subobj); + subobj = Tcl_NewDoubleObj(imgPtr->y); + Tcl_ListObjAppendElement(interp, obj, subobj); + Tcl_SetObjResult(interp, obj); + } else if (argc < 3) { + if (argc==1) { + if (Tcl_ListObjGetElements(interp, argv[0], &argc, + (Tcl_Obj ***) &argv) != TCL_OK) { + return TCL_ERROR; + } else if (argc != 2) { + char buf[64]; + + sprintf(buf, "wrong # coordinates: expected 2, got %d", argc); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_ERROR; + } + } + if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &imgPtr->x) != TCL_OK) + || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1], + &imgPtr->y) != TCL_OK)) { return TCL_ERROR; } ComputeImageBbox(canvas, imgPtr); @@ -257,7 +311,7 @@ ConfigureImage(interp, canvas, itemPtr, argc, argv, flags) Tk_Canvas canvas; /* Canvas containing itemPtr. */ Tk_Item *itemPtr; /* Image item to reconfigure. */ int argc; /* Number of elements in argv. */ - char **argv; /* Arguments describing things to configure. */ + Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */ int flags; /* Flags to pass to Tk_ConfigureWidget. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; @@ -265,8 +319,8 @@ ConfigureImage(interp, canvas, itemPtr, argc, argv, flags) Tk_Image image; tkwin = Tk_CanvasTkwin(canvas); - if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, - argv, (char *) imgPtr, flags) != TCL_OK) { + if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv, + (char *) imgPtr, flags|TK_CONFIG_OBJS) != TCL_OK) { return TCL_ERROR; } @@ -277,6 +331,11 @@ ConfigureImage(interp, canvas, itemPtr, argc, argv, flags) * if it hasn't changed. */ + if (imgPtr->activeImageString != NULL) { + itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT; + } else { + itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT; + } if (imgPtr->imageString != NULL) { image = Tk_GetImage(interp, tkwin, imgPtr->imageString, ImageChangedProc, (ClientData) imgPtr); @@ -290,6 +349,32 @@ ConfigureImage(interp, canvas, itemPtr, argc, argv, flags) Tk_FreeImage(imgPtr->image); } imgPtr->image = image; + if (imgPtr->activeImageString != NULL) { + image = Tk_GetImage(interp, tkwin, imgPtr->activeImageString, + ImageChangedProc, (ClientData) imgPtr); + if (image == NULL) { + return TCL_ERROR; + } + } else { + image = NULL; + } + if (imgPtr->activeImage != NULL) { + Tk_FreeImage(imgPtr->activeImage); + } + imgPtr->activeImage = image; + if (imgPtr->disabledImageString != NULL) { + image = Tk_GetImage(interp, tkwin, imgPtr->disabledImageString, + ImageChangedProc, (ClientData) imgPtr); + if (image == NULL) { + return TCL_ERROR; + } + } else { + image = NULL; + } + if (imgPtr->disabledImage != NULL) { + Tk_FreeImage(imgPtr->disabledImage); + } + imgPtr->disabledImage = image; ComputeImageBbox(canvas, imgPtr); return TCL_OK; } @@ -323,9 +408,21 @@ DeleteImage(canvas, itemPtr, display) if (imgPtr->imageString != NULL) { ckfree(imgPtr->imageString); } + if (imgPtr->activeImageString != NULL) { + ckfree(imgPtr->activeImageString); + } + if (imgPtr->disabledImageString != NULL) { + ckfree(imgPtr->disabledImageString); + } if (imgPtr->image != NULL) { Tk_FreeImage(imgPtr->image); } + if (imgPtr->activeImage != NULL) { + Tk_FreeImage(imgPtr->activeImage); + } + if (imgPtr->disabledImage != NULL) { + Tk_FreeImage(imgPtr->disabledImage); + } } /* @@ -357,11 +454,27 @@ ComputeImageBbox(canvas, imgPtr) { int width, height; int x, y; + Tk_Image image; + Tk_State state = imgPtr->header.state; + + if(state == TK_STATE_NULL) { + state = ((TkCanvas *)canvas)->canvas_state; + } + image = imgPtr->image; + if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)imgPtr) { + if (imgPtr->activeImage != NULL) { + image = imgPtr->activeImage; + } + } else if (state == TK_STATE_DISABLED) { + if (imgPtr->disabledImage != NULL) { + image = imgPtr->disabledImage; + } + } x = (int) (imgPtr->x + ((imgPtr->x >= 0) ? 0.5 : - 0.5)); y = (int) (imgPtr->y + ((imgPtr->y >= 0) ? 0.5 : - 0.5)); - if (imgPtr->image == None) { + if ((state == TK_STATE_HIDDEN) || (image == None)) { imgPtr->header.x1 = imgPtr->header.x2 = x; imgPtr->header.y1 = imgPtr->header.y2 = y; return; @@ -371,7 +484,7 @@ ComputeImageBbox(canvas, imgPtr) * Compute location and size of image, using anchor information. */ - Tk_SizeOfImage(imgPtr->image, &width, &height); + Tk_SizeOfImage(image, &width, &height); switch (imgPtr->anchor) { case TK_ANCHOR_N: x -= width/2; @@ -445,8 +558,25 @@ DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height) { ImageItem *imgPtr = (ImageItem *) itemPtr; short drawableX, drawableY; + Tk_Image image; + Tk_State state = itemPtr->state; + + if(state == TK_STATE_NULL) { + state = ((TkCanvas *)canvas)->canvas_state; + } - if (imgPtr->image == NULL) { + image = imgPtr->image; + if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) { + if (imgPtr->activeImage != NULL) { + image = imgPtr->activeImage; + } + } else if (state == TK_STATE_DISABLED) { + if (imgPtr->disabledImage != NULL) { + image = imgPtr->disabledImage; + } + } + + if (image == NULL) { return; } @@ -456,7 +586,7 @@ DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height) Tk_CanvasDrawableCoords(canvas, (double) x, (double) y, &drawableX, &drawableY); - Tk_RedrawImage(imgPtr->image, x - imgPtr->header.x1, y - imgPtr->header.y1, + Tk_RedrawImage(image, x - imgPtr->header.x1, y - imgPtr->header.y1, width, height, drawable, drawableX, drawableY); } @@ -565,6 +695,96 @@ ImageToArea(canvas, itemPtr, rectPtr) /* *-------------------------------------------------------------- * + * ImageToPostscript -- + * + * This procedure is called to generate Postscript for + * image items. + * + * Results: + * The return value is a standard Tcl result. If an error + * occurs in generating Postscript then an error message is + * left in interp->result, replacing whatever used to be there. + * If no error occurs, then Postscript for the item is appended + * to the result. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static int +ImageToPostscript(interp, canvas, itemPtr, prepass) + Tcl_Interp *interp; /* Leave Postscript or error message + * here. */ + Tk_Canvas canvas; /* Information about overall canvas. */ + Tk_Item *itemPtr; /* Item for which Postscript is + * wanted. */ + int prepass; /* 1 means this is a prepass to + * collect font information; 0 means + * final Postscript is being created.*/ +{ + ImageItem *imgPtr = (ImageItem *)itemPtr; + Tk_Window canvasWin = Tk_CanvasTkwin(canvas); + + char buffer[256]; + double x, y; + int width, height; + Tk_Image image; + Tk_State state = itemPtr->state; + + if(state == TK_STATE_NULL) { + state = ((TkCanvas *)canvas)->canvas_state; + } + + image = imgPtr->image; + if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) { + if (imgPtr->activeImage != NULL) { + image = imgPtr->activeImage; + } + } else if (state == TK_STATE_DISABLED) { + if (imgPtr->disabledImage != NULL) { + image = imgPtr->disabledImage; + } + } + Tk_SizeOfImage(image, &width, &height); + + /* + * Compute the coordinates of the lower-left corner of the image, + * taking into account the anchor position for the image. + */ + + x = imgPtr->x; + y = Tk_CanvasPsY(canvas, imgPtr->y); + + switch (imgPtr->anchor) { + case TK_ANCHOR_NW: y -= height; break; + case TK_ANCHOR_N: x -= width/2.0; y -= height; break; + case TK_ANCHOR_NE: x -= width; y -= height; break; + case TK_ANCHOR_E: x -= width; y -= height/2.0; break; + case TK_ANCHOR_SE: x -= width; break; + case TK_ANCHOR_S: x -= width/2.0; break; + case TK_ANCHOR_SW: break; + case TK_ANCHOR_W: y -= height/2.0; break; + case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; + } + + if (image == NULL) { + return TCL_OK; + } + + if (!prepass) { + sprintf(buffer, "%.15g %.15g", x, y); + Tcl_AppendResult(interp, buffer, " translate\n", (char *) NULL); + } + + return Tk_PostscriptImage(image, interp, canvasWin, + ((TkCanvas *) canvas)->psInfo, 0, 0, width, height, prepass); +} + +/* + *-------------------------------------------------------------- + * * ScaleImage -- * * This procedure is invoked to rescale an item. |