diff options
author | drh <drh@sqlite.org> | 2001-07-14 15:53:53 (GMT) |
---|---|---|
committer | drh <drh@sqlite.org> | 2001-07-14 15:53:53 (GMT) |
commit | c7f37e9d0848caca401986cdbf53b64a271f40e6 (patch) | |
tree | 5f201478be2048c4603ec053f2ff842d0ec35450 /generic | |
parent | 29effb59e09d1f7eab3016936a53e909d40aed16 (diff) | |
download | tk-c7f37e9d0848caca401986cdbf53b64a271f40e6.zip tk-c7f37e9d0848caca401986cdbf53b64a271f40e6.tar.gz tk-c7f37e9d0848caca401986cdbf53b64a271f40e6.tar.bz2 |
The code for generating postscript of a bitmap image was apparently never
completed. The beginnings of the code was there but it generated
diagnostic messages rather than proper postscript. This change fixes
the problem.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tkImgBmap.c | 186 |
1 files changed, 140 insertions, 46 deletions
diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c index 6c49129..8f03e74 100644 --- a/generic/tkImgBmap.c +++ b/generic/tkImgBmap.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkImgBmap.c,v 1.11 1999/12/14 06:52:28 hobbs Exp $ + * RCS: @(#) $Id: tkImgBmap.c,v 1.12 2001/07/14 15:53:53 drh Exp $ */ #include "tkInt.h" @@ -1105,13 +1105,106 @@ GetByte(chan) /* *---------------------------------------------------------------------- * + * ImgBmapPsImagemask -- + * + * This procedure generates postscript suitable for rendering a + * single bitmap of an image. A single bitmap image might contain both + * a foreground and a background bitmap. This routine is called once + * for each such bitmap in a bitmap image. + * + * Prior to invoking this routine, the following setup has occurred: + * + * 1. The postscript foreground color has been set to the color + * used to render the bitmap. + * + * 2. The origin of the postscript coordinate system is set to + * the lower left corner of the bitmap. + * + * 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. + * + * Side effects: + * Postscript code is appended to interp->result. + * + *---------------------------------------------------------------------- + */ + +static int +ImgBmapPsImagemask(interp, width, height, data) + Tcl_Interp *interp; /* Append postscript to this interpreter */ + int width, height; /* Width and height of the bitmap in pixels */ + 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 + * postscript uses. (In Tk, the least significant bit is on the right + * side of the bitmap and in postscript the least significant bit is shown + * on the left.) The following array is used to reverse the order of bits + * within a byte so that the bits will be in the order postscript expects. + */ + static unsigned char bit_reverse[] = { + 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, + 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, + 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, + 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, + 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, + 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, + 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, + 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, + 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, + 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, + 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, + 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, + 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, + 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, + 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, + 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", 0); + return TCL_ERROR; + } + sprintf(buffer, "0 0 moveto %d %d true [%d 0 0 %d 0 %d] {<\n", + width, height, width, -height, height); + Tcl_AppendResult(interp, buffer, 0); + nBytePerRow = (width+7)/8; + for(i=0; i<height; i++){ + for(j=0; j<nBytePerRow; j++){ + sprintf(buffer, " %02x", bit_reverse[0xff & data[i*nBytePerRow + j]]); + Tcl_AppendResult(interp, buffer, 0); + } + Tcl_AppendResult(interp, "\n", 0); + } + Tcl_AppendResult(interp, ">} imagemask \n", 0); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * ImgBmapPostscript -- * - * This procedure is called by the image code to create - * postscript output for an image. + * This procedure generates postscript for rendering a bitmap image. * * Results: - * None. + * 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. * * Side effects: * None. @@ -1129,74 +1222,75 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, int x, y, width, height, prepass; { BitmapMaster *masterPtr = (BitmapMaster *) clientData; - int rowsAtOnce, rowsThisTime; - int curRow, yy; char buffer[200]; if (prepass) { return TCL_OK; } + + /* + * There is nothing to do for bitmaps with zero width or height + */ + if( width<=0 || height<=0 || masterPtr->width<=0 || masterPtr->height<=0 ){ + return TCL_OK; + } + /* - * Color the background, if there is one. + * 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 function put a "gsave" into the postscript and + * will add a "grestore" at after this routine returns, so it is safe + * to make whatever changes are necessary here. */ + if( x!=0 || y!=0 ){ + sprintf(buffer, "%d %d moveto\n", x, y); + Tcl_AppendResult(interp, buffer, 0); + } + if( width!=1 || height!=1 ){ + sprintf(buffer, "%d %d scale\n", width, height); + Tcl_AppendResult(interp, buffer, 0); + } - if (masterPtr->bgUid != NULL) { + /* + * Color the background, if there is one. This step is skipped if the + * background is transparent. If the background is not transparent and + * there is no background mask, then color the complete rectangle that + * encloses the bitmap. If there is a background mask, then only apply + * color to the bits specified by the mask. + */ + if ((masterPtr->bgUid != NULL) && (masterPtr->bgUid[0] != '\000')) { XColor color; XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid, &color); - sprintf(buffer, - "%d %d moveto %d 0 rlineto 0 %d rlineto %d %s\n", - x, y, width, height, -width,"0 rlineto closepath"); - Tcl_AppendResult(interp, buffer, (char *) NULL); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { return TCL_ERROR; } - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + if (masterPtr->maskData == NULL) { + Tcl_AppendResult(interp, + "0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto " + "closepath fill\n", 0 + ); + } else if (ImgBmapPsImagemask(interp, masterPtr->width, + masterPtr->height, masterPtr->maskData) != TCL_OK) { + return TCL_ERROR; + } } /* - * Draw the bitmap, if there is a foreground color. If the bitmap - * is very large, then chop it up into multiple bitmaps, each - * consisting of one or more rows. This is needed because Postscript - * can't handle single strings longer than 64 KBytes long. + * Draw the bitmap foreground, assuming there is one. */ - - if (masterPtr->fgUid != NULL) { + if ( (masterPtr->fgUid != NULL) && (masterPtr->data != NULL) ) { XColor color; XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid, &color); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { return TCL_ERROR; } - if (width > 60000) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "can't generate Postscript", - " for bitmaps more than 60000 pixels wide", - (char *) NULL); + if (ImgBmapPsImagemask(interp, masterPtr->width, masterPtr->height, + masterPtr->data) != TCL_OK) { return TCL_ERROR; } - rowsAtOnce = 60000/width; - if (rowsAtOnce < 1) { - rowsAtOnce = 1; - } - sprintf(buffer, "%d %d translate\n", x, y); - Tcl_AppendResult(interp, buffer, (char *) NULL); - for (curRow = y+height-1; curRow >= y; curRow -= rowsAtOnce) { - rowsThisTime = rowsAtOnce; - if (rowsThisTime > (curRow + 1 - y)) { - rowsThisTime = curRow + 1 - y; - } - sprintf(buffer, "%d %d", width, rowsThisTime); - Tcl_AppendResult(interp, buffer, " true matrix {\n<", - (char *) NULL); - for (yy = curRow; yy >= (curRow - rowsThisTime + 1); yy--) { - sprintf(buffer, "row %d\n", yy); - Tcl_AppendResult(interp, buffer, (char *) NULL); - } - sprintf(buffer, "0 %.15g", (double) rowsThisTime); - Tcl_AppendResult(interp, ">\n} imagemask\n", buffer, - " translate\n", (char *) NULL); - } } return TCL_OK; } |