diff options
Diffstat (limited to 'generic/tkImgBmap.c')
-rw-r--r-- | generic/tkImgBmap.c | 262 |
1 files changed, 147 insertions, 115 deletions
diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c index 4f5c6ac..bbc471e 100644 --- a/generic/tkImgBmap.c +++ b/generic/tkImgBmap.c @@ -75,8 +75,8 @@ typedef struct BitmapInstance { static int GetByte(Tcl_Channel chan); static int ImgBmapCreate(Tcl_Interp *interp, - char *name, int argc, Tcl_Obj *CONST objv[], - Tk_ImageType *typePtr, Tk_ImageMaster master, + const char *name, int argc, Tcl_Obj *const objv[], + const Tk_ImageType *typePtr, Tk_ImageMaster master, ClientData *clientDataPtr); static ClientData ImgBmapGet(Tk_Window tkwin, ClientData clientData); static void ImgBmapDisplay(ClientData clientData, @@ -98,27 +98,28 @@ Tk_ImageType tkBitmapImageType = { ImgBmapFree, /* freeProc */ ImgBmapDelete, /* deleteProc */ ImgBmapPostscript, /* postscriptProc */ - NULL /* nextPtr */ + NULL, /* nextPtr */ + NULL }; /* * Information used for parsing configuration specs: */ -static Tk_ConfigSpec configSpecs[] = { +static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_UID, "-background", NULL, NULL, - "", Tk_Offset(BitmapMaster, bgUid), 0}, + "", Tk_Offset(BitmapMaster, bgUid), 0, NULL}, {TK_CONFIG_STRING, "-data", NULL, NULL, - NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK}, + NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_STRING, "-file", NULL, NULL, - NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK}, + NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_UID, "-foreground", NULL, NULL, - "#000000", Tk_Offset(BitmapMaster, fgUid), 0}, + "#000000", Tk_Offset(BitmapMaster, fgUid), 0, NULL}, {TK_CONFIG_STRING, "-maskdata", NULL, NULL, - NULL, Tk_Offset(BitmapMaster, maskDataString), TK_CONFIG_NULL_OK}, + NULL, Tk_Offset(BitmapMaster, maskDataString), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_STRING, "-maskfile", NULL, NULL, - NULL, Tk_Offset(BitmapMaster, maskFileString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} + NULL, Tk_Offset(BitmapMaster, maskFileString), TK_CONFIG_NULL_OK, NULL}, + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; /* @@ -129,7 +130,7 @@ static Tk_ConfigSpec configSpecs[] = { #define MAX_WORD_LENGTH 100 typedef struct ParseInfo { - char *string; /* Next character of string data for bitmap, + const char *string; /* Next character of string data for bitmap, * or NULL if bitmap is being read from * file. */ Tcl_Channel chan; /* File containing bitmap data, or NULL if no @@ -145,11 +146,11 @@ typedef struct ParseInfo { */ static int ImgBmapCmd(ClientData clientData, Tcl_Interp *interp, - int argc, Tcl_Obj *CONST objv[]); + int argc, Tcl_Obj *const objv[]); static void ImgBmapCmdDeletedProc(ClientData clientData); static void ImgBmapConfigureInstance(BitmapInstance *instancePtr); static int ImgBmapConfigureMaster(BitmapMaster *masterPtr, - int argc, Tcl_Obj *CONST objv[], int flags); + int argc, Tcl_Obj *const objv[], int flags); static int NextBitmapWord(ParseInfo *parseInfoPtr); /* @@ -173,23 +174,22 @@ static int ImgBmapCreate( Tcl_Interp *interp, /* Interpreter for application containing * image. */ - char *name, /* Name to use for image. */ + const char *name, /* Name to use for image. */ int argc, /* Number of arguments. */ - Tcl_Obj *CONST argv[], /* Argument objects for options (doesn't + Tcl_Obj *const argv[], /* Argument objects for options (doesn't * include image name or type). */ - Tk_ImageType *typePtr, /* Pointer to our type record (not used). */ + const Tk_ImageType *typePtr,/* Pointer to our type record (not used). */ Tk_ImageMaster master, /* Token for image, to be used by us in later * callbacks. */ ClientData *clientDataPtr) /* Store manager's token for image here; it * will be returned in later callbacks. */ { - BitmapMaster *masterPtr; + BitmapMaster *masterPtr = ckalloc(sizeof(BitmapMaster)); - masterPtr = (BitmapMaster *) ckalloc(sizeof(BitmapMaster)); masterPtr->tkMaster = master; masterPtr->interp = interp; masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgBmapCmd, - (ClientData) masterPtr, ImgBmapCmdDeletedProc); + masterPtr, ImgBmapCmdDeletedProc); masterPtr->width = masterPtr->height = 0; masterPtr->data = NULL; masterPtr->maskData = NULL; @@ -201,10 +201,10 @@ ImgBmapCreate( masterPtr->maskDataString = NULL; masterPtr->instancePtr = NULL; if (ImgBmapConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) { - ImgBmapDelete((ClientData) masterPtr); + ImgBmapDelete(masterPtr); return TCL_ERROR; } - *clientDataPtr = (ClientData) masterPtr; + *clientDataPtr = masterPtr; return TCL_OK; } @@ -233,26 +233,25 @@ ImgBmapConfigureMaster( BitmapMaster *masterPtr, /* Pointer to data structure describing * overall bitmap image to (reconfigure). */ int objc, /* Number of entries in objv. */ - Tcl_Obj *CONST objv[], /* Pairs of configuration options for image. */ + Tcl_Obj *const objv[], /* Pairs of configuration options for image. */ int flags) /* Flags to pass to Tk_ConfigureWidget, such * as TK_CONFIG_ARGV_ONLY. */ { BitmapInstance *instancePtr; int maskWidth, maskHeight, dummy1, dummy2; + const char **argv = ckalloc((objc+1) * sizeof(char *)); - CONST char **argv = (CONST char **) ckalloc((objc+1) * sizeof(char *)); for (dummy1 = 0; dummy1 < objc; dummy1++) { - argv[dummy1]=Tcl_GetString(objv[dummy1]); + argv[dummy1] = Tcl_GetString(objv[dummy1]); } argv[objc] = NULL; if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp), - configSpecs, objc, argv, (char *) masterPtr, flags) - != TCL_OK) { - ckfree((char *) argv); + configSpecs, objc, argv, (char *) masterPtr, flags) != TCL_OK) { + ckfree(argv); return TCL_ERROR; } - ckfree((char *) argv); + ckfree(argv); /* * Parse the bitmap and/or mask to create binary data. Make sure that the @@ -278,8 +277,10 @@ ImgBmapConfigureMaster( if ((masterPtr->maskFileString != NULL) || (masterPtr->maskDataString != NULL)) { if (masterPtr->data == NULL) { - Tcl_SetResult(masterPtr->interp, "can't have mask without bitmap", - TCL_STATIC); + Tcl_SetObjResult(masterPtr->interp, Tcl_NewStringObj( + "can't have mask without bitmap", -1)); + Tcl_SetErrorCode(masterPtr->interp, "TK", "IMAGE", "BITMAP", + "NO_BITMAP", NULL); return TCL_ERROR; } masterPtr->maskData = TkGetBitmapData(masterPtr->interp, @@ -292,8 +293,10 @@ ImgBmapConfigureMaster( || (maskHeight != masterPtr->height)) { ckfree(masterPtr->maskData); masterPtr->maskData = NULL; - Tcl_SetResult(masterPtr->interp, - "bitmap and mask have different sizes", TCL_STATIC); + Tcl_SetObjResult(masterPtr->interp, Tcl_NewStringObj( + "bitmap and mask have different sizes", -1)); + Tcl_SetErrorCode(masterPtr->interp, "TK", "IMAGE", "BITMAP", + "MASK_SIZE", NULL); return TCL_ERROR; } } @@ -327,7 +330,7 @@ ImgBmapConfigureMaster( * None. * * Side effects: - * Generates errors via Tcl_BackgroundError if there are problems in + * Generates errors via Tcl_BackgroundException if there are problems in * setting up the instance. * *---------------------------------------------------------------------- @@ -442,10 +445,10 @@ ImgBmapConfigureInstance( Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc); } instancePtr->gc = None; - Tcl_AddErrorInfo(masterPtr->interp, "\n (while configuring image \""); - Tcl_AddErrorInfo(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster)); - Tcl_AddErrorInfo(masterPtr->interp, "\")"); - Tcl_BackgroundError(masterPtr->interp); + Tcl_AppendObjToErrorInfo(masterPtr->interp, Tcl_ObjPrintf( + "\n (while configuring image \"%s\")", Tk_NameOfImage( + masterPtr->tkMaster))); + Tcl_BackgroundException(masterPtr->interp, TCL_ERROR); } /* @@ -473,8 +476,8 @@ ImgBmapConfigureInstance( char * TkGetBitmapData( Tcl_Interp *interp, /* For reporting errors, or NULL. */ - char *string, /* String describing bitmap. May be NULL. */ - char *fileName, /* Name of file containing bitmap description. + const char *string, /* String describing bitmap. May be NULL. */ + const char *fileName, /* Name of file containing bitmap description. * Used only if string is NULL. Must not be * NULL if string is NULL. */ int *widthPtr, int *heightPtr, @@ -482,7 +485,7 @@ TkGetBitmapData( int *hotXPtr, int *hotYPtr) /* Position of hot spot or -1,-1. */ { int width, height, numBytes, hotX, hotY; - CONST char *expandedFileName; + const char *expandedFileName; char *p, *end; ParseInfo pi; char *data = NULL; @@ -491,8 +494,10 @@ TkGetBitmapData( pi.string = string; if (string == NULL) { if ((interp != NULL) && Tcl_IsSafe(interp)) { - Tcl_AppendResult(interp, "can't get bitmap data from a file in a", - " safe interpreter", NULL); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "can't get bitmap data from a file in a safe interpreter", + -1)); + Tcl_SetErrorCode(interp, "TK", "SAFE", "BITMAP_FILE", NULL); return NULL; } expandedFileName = Tcl_TranslateFileName(interp, fileName, &buffer); @@ -504,8 +509,9 @@ TkGetBitmapData( if (pi.chan == NULL) { if (interp != NULL) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "couldn't read bitmap file \"", - fileName, "\": ", Tcl_PosixError(interp), NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "couldn't read bitmap file \"%s\": %s", + fileName, Tcl_PosixError(interp))); } return NULL; } @@ -594,8 +600,11 @@ TkGetBitmapData( } } else if ((pi.word[0] == '{') && (pi.word[1] == 0)) { if (interp != NULL) { - Tcl_AppendResult(interp, "format error in bitmap data; ", - "looks like it's an obsolete X10 bitmap file", NULL); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "format error in bitmap data; looks like it's an" + " obsolete X10 bitmap file", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "BITMAP", "OBSOLETE", + NULL); } goto errorCleanup; } @@ -611,7 +620,7 @@ TkGetBitmapData( goto error; } numBytes = ((width+7)/8) * height; - data = (char *) ckalloc((unsigned) numBytes); + data = ckalloc(numBytes); for (p = data; numBytes > 0; p++, numBytes--) { if (NextBitmapWord(&pi) != TCL_OK) { goto error; @@ -637,7 +646,9 @@ TkGetBitmapData( error: if (interp != NULL) { - Tcl_SetResult(interp, "format error in bitmap data", TCL_STATIC); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "format error in bitmap data", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "BITMAP", "FORMAT", NULL); } errorCleanup: @@ -674,7 +685,8 @@ NextBitmapWord( ParseInfo *parseInfoPtr) /* Describes what we're reading and where we * are in it. */ { - char *src, *dst; + const char *src; + char *dst; int c; parseInfoPtr->wordLength = 0; @@ -742,14 +754,14 @@ ImgBmapCmd( ClientData clientData, /* Information about the image master. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - static CONST char *bmapOptions[] = {"cget", "configure", NULL}; - BitmapMaster *masterPtr = (BitmapMaster *) clientData; + static const char *const bmapOptions[] = {"cget", "configure", NULL}; + BitmapMaster *masterPtr = clientData; int index; if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], bmapOptions, "option", 0, @@ -807,7 +819,7 @@ ImgBmapGet( ClientData masterData) /* Pointer to our master structure for the * image. */ { - BitmapMaster *masterPtr = (BitmapMaster *) masterData; + BitmapMaster *masterPtr = masterData; BitmapInstance *instancePtr; /* @@ -819,7 +831,7 @@ ImgBmapGet( instancePtr = instancePtr->nextPtr) { if (instancePtr->tkwin == tkwin) { instancePtr->refCount++; - return (ClientData) instancePtr; + return instancePtr; } } @@ -828,7 +840,7 @@ ImgBmapGet( * the image. */ - instancePtr = (BitmapInstance *) ckalloc(sizeof(BitmapInstance)); + instancePtr = ckalloc(sizeof(BitmapInstance)); instancePtr->refCount = 1; instancePtr->masterPtr = masterPtr; instancePtr->tkwin = tkwin; @@ -850,7 +862,7 @@ ImgBmapGet( masterPtr->height); } - return (ClientData) instancePtr; + return instancePtr; } /* @@ -882,7 +894,7 @@ ImgBmapDisplay( /* Coordinates within drawable that correspond * to imageX and imageY. */ { - BitmapInstance *instancePtr = (BitmapInstance *) clientData; + BitmapInstance *instancePtr = clientData; int masking; /* @@ -936,7 +948,7 @@ ImgBmapFree( * instance to be displayed. */ Display *display) /* Display containing window that used image. */ { - BitmapInstance *instancePtr = (BitmapInstance *) clientData; + BitmapInstance *instancePtr = clientData; BitmapInstance *prevPtr; instancePtr->refCount--; @@ -973,7 +985,7 @@ ImgBmapFree( } prevPtr->nextPtr = instancePtr->nextPtr; } - ckfree((char *) instancePtr); + ckfree(instancePtr); } /* @@ -998,7 +1010,7 @@ ImgBmapDelete( ClientData masterData) /* Pointer to BitmapMaster structure for * image. Must not have any more instances. */ { - BitmapMaster *masterPtr = (BitmapMaster *) masterData; + BitmapMaster *masterPtr = masterData; if (masterPtr->instancePtr != NULL) { Tcl_Panic("tried to delete bitmap image when instances still exist"); @@ -1014,7 +1026,7 @@ ImgBmapDelete( ckfree(masterPtr->maskData); } Tk_FreeOptions(configSpecs, (char *) masterPtr, NULL, 0); - ckfree((char *) masterPtr); + ckfree(masterPtr); } /* @@ -1039,7 +1051,7 @@ ImgBmapCmdDeletedProc( ClientData clientData) /* Pointer to BitmapMaster structure for * image. */ { - BitmapMaster *masterPtr = (BitmapMaster *) clientData; + BitmapMaster *masterPtr = clientData; masterPtr->imageCmd = NULL; if (masterPtr->tkMaster != NULL) { @@ -1077,7 +1089,6 @@ GetByte( return buffer; } } - /* *---------------------------------------------------------------------- @@ -1100,28 +1111,22 @@ GetByte( * 3. The postscript coordinate system has been scaled so that the * entire bitmap is one unit squared. * - * Some postscript implementations cannot handle bitmap strings longer - * than about 60k characters. If the bitmap data is that big or bigger, - * then we render it by splitting it into several smaller bitmaps. - * * Results: - * Returns TCL_OK on success. Returns TCL_ERROR and leaves and error - * message in interp->result if there is a problem. + * None. * * Side effects: - * Postscript code is appended to interp->result. + * Postscript code is appended to psObj. * *---------------------------------------------------------------------- */ -static int +static void ImgBmapPsImagemask( - Tcl_Interp *interp, /* Append postscript to this interpreter */ + Tcl_Obj *psObj, /* Append postscript to this buffer. */ int width, int height, /* Width and height of the bitmap in pixels */ - char *data) /* Data for the bitmap */ + char *data) /* Data for the bitmap. */ { int i, j, nBytePerRow; - char buffer[200]; /* * The bit order of bitmaps in Tk is the opposite of the bit order that @@ -1150,29 +1155,20 @@ ImgBmapPsImagemask( 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255, }; - if (width*height > 60000) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "unable to generate postscript for bitmaps " - "larger than 60000 pixels", NULL); - return TCL_ERROR; - } - - sprintf(buffer, "0 0 moveto %d %d true [%d 0 0 %d 0 %d] {<\n", + Tcl_AppendPrintfToObj(psObj, + "0 0 moveto %d %d true [%d 0 0 %d 0 %d] {<\n", width, height, width, -height, height); - Tcl_AppendResult(interp, buffer, NULL); - nBytePerRow = (width+7)/8; - for(i=0; i<height; i++){ - for(j=0; j<nBytePerRow; j++){ - sprintf(buffer, " %02x", + nBytePerRow = (width + 7) / 8; + for (i=0; i<height; i++) { + for (j=0; j<nBytePerRow; j++) { + Tcl_AppendPrintfToObj(psObj, " %02x", bit_reverse[0xff & data[i*nBytePerRow + j]]); - Tcl_AppendResult(interp, buffer, NULL); } - Tcl_AppendResult(interp, "\n", NULL); + Tcl_AppendToObj(psObj, "\n", -1); } - Tcl_AppendResult(interp, ">} imagemask \n", NULL); - return TCL_OK; + Tcl_AppendToObj(psObj, ">} imagemask \n", -1); } /* @@ -1183,7 +1179,6 @@ ImgBmapPsImagemask( * This procedure generates postscript for rendering a bitmap image. * * Results: - * On success, this routine writes postscript code into interp->result * and returns TCL_OK TCL_ERROR is returned and an error message is left * in interp->result if anything goes wrong. @@ -1203,8 +1198,9 @@ ImgBmapPostscript( int x, int y, int width, int height, int prepass) { - BitmapMaster *masterPtr = (BitmapMaster *) clientData; - char buffer[200]; + BitmapMaster *masterPtr = clientData; + Tcl_InterpState interpState; + Tcl_Obj *psObj; if (prepass) { return TCL_OK; @@ -1214,11 +1210,32 @@ ImgBmapPostscript( * There is nothing to do for bitmaps with zero width or height. */ - if (width<=0 || height<=0 || masterPtr->width<=0 || masterPtr->height<= 0){ + if (width<=0 || height<=0 || masterPtr->width<=0 || masterPtr->height<=0){ return TCL_OK; } /* + * Some postscript implementations cannot handle bitmap strings longer + * than about 60k characters. If the bitmap data is that big or bigger, + * we bail out. + */ + + if (masterPtr->width*masterPtr->height > 60000) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "unable to generate postscript for bitmaps larger than 60000" + " pixels", -1)); + Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "MEMLIMIT", NULL); + return TCL_ERROR; + } + + /* + * Make our working space. + */ + + psObj = Tcl_NewObj(); + interpState = Tcl_SaveInterpState(interp, TCL_OK); + + /* * Translate the origin of the coordinate system to be the lower-left * corner of the bitmap and adjust the scale of the coordinate system so * that entire bitmap covers one square unit of the page. The calling @@ -1227,13 +1244,11 @@ ImgBmapPostscript( * necessary here. */ - if (x!=0 || y!=0) { - sprintf(buffer, "%d %d moveto\n", x, y); - Tcl_AppendResult(interp, buffer, NULL); + if (x != 0 || y != 0) { + Tcl_AppendPrintfToObj(psObj, "%d %d moveto\n", x, y); } - if (width!=1 || height!=1) { - sprintf(buffer, "%d %d scale\n", width, height); - Tcl_AppendResult(interp, buffer, NULL); + if (width != 1 || height != 1) { + Tcl_AppendPrintfToObj(psObj, "%d %d scale\n", width, height); } /* @@ -1249,16 +1264,19 @@ ImgBmapPostscript( TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid, &color); + Tcl_ResetResult(interp); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { - return TCL_ERROR; + goto error; } + Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); + if (masterPtr->maskData == NULL) { - Tcl_AppendResult(interp, - "0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto ", - "closepath fill\n", NULL); - } else if (ImgBmapPsImagemask(interp, masterPtr->width, - masterPtr->height, masterPtr->maskData) != TCL_OK) { - return TCL_ERROR; + Tcl_AppendToObj(psObj, + "0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto " + "closepath fill\n", -1); + } else { + ImgBmapPsImagemask(psObj, masterPtr->width, masterPtr->height, + masterPtr->maskData); } } @@ -1271,15 +1289,29 @@ ImgBmapPostscript( TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid, &color); + Tcl_ResetResult(interp); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { - return TCL_ERROR; - } - if (ImgBmapPsImagemask(interp, masterPtr->width, masterPtr->height, - masterPtr->data) != TCL_OK) { - return TCL_ERROR; + goto error; } + Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); + + ImgBmapPsImagemask(psObj, masterPtr->width, masterPtr->height, + masterPtr->data); } + + /* + * Plug the accumulated postscript back into the result. + */ + + (void) Tcl_RestoreInterpState(interp, interpState); + Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj); + Tcl_DecrRefCount(psObj); return TCL_OK; + + error: + Tcl_DiscardInterpState(interpState); + Tcl_DecrRefCount(psObj); + return TCL_ERROR; } /* |