summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tkImgBmap.c186
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;
}