4 * This file implements bitmap items for canvas widgets.
6 * Copyright (c) 1992-1994 The Regents of the University of California.
7 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
9 * See the file "license.terms" for information on usage and redistribution of
10 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
18 * The structure below defines the record for each bitmap item.
21 typedef struct BitmapItem {
22 Tk_Item header; /* Generic stuff that's the same for all
23 * types. MUST BE FIRST IN STRUCTURE. */
24 double x, y; /* Coordinates of positioning point for
26 Tk_Anchor anchor; /* Where to anchor bitmap relative to (x,y) */
27 Pixmap bitmap; /* Bitmap to display in window. */
28 Pixmap activeBitmap; /* Bitmap to display in window. */
29 Pixmap disabledBitmap; /* Bitmap to display in window. */
30 XColor *fgColor; /* Foreground color to use for bitmap. */
31 XColor *activeFgColor; /* Foreground color to use for bitmap. */
32 XColor *disabledFgColor; /* Foreground color to use for bitmap. */
33 XColor *bgColor; /* Background color to use for bitmap. */
34 XColor *activeBgColor; /* Background color to use for bitmap. */
35 XColor *disabledBgColor; /* Background color to use for bitmap. */
36 GC gc; /* Graphics context to use for drawing bitmap
41 * Information used for parsing configuration specs:
44 static const Tk_CustomOption stateOption = {
45 TkStateParseProc, TkStatePrintProc, INT2PTR(2)
47 static const Tk_CustomOption tagsOption = {
48 Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
51 static const Tk_ConfigSpec configSpecs[] = {
52 {TK_CONFIG_COLOR, "-activebackground", NULL, NULL,
53 NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK, NULL},
54 {TK_CONFIG_BITMAP, "-activebitmap", NULL, NULL,
55 NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK, NULL},
56 {TK_CONFIG_COLOR, "-activeforeground", NULL, NULL,
57 NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK, NULL},
58 {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
59 "center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
60 {TK_CONFIG_COLOR, "-background", NULL, NULL,
61 NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK, NULL},
62 {TK_CONFIG_BITMAP, "-bitmap", NULL, NULL,
63 NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK, NULL},
64 {TK_CONFIG_COLOR, "-disabledbackground", NULL, NULL,
65 NULL, Tk_Offset(BitmapItem, disabledBgColor),
66 TK_CONFIG_NULL_OK, NULL},
67 {TK_CONFIG_BITMAP, "-disabledbitmap", NULL, NULL,
68 NULL, Tk_Offset(BitmapItem, disabledBitmap),
69 TK_CONFIG_NULL_OK, NULL},
70 {TK_CONFIG_COLOR, "-disabledforeground", NULL, NULL,
71 NULL, Tk_Offset(BitmapItem, disabledFgColor),
72 TK_CONFIG_NULL_OK, NULL},
73 {TK_CONFIG_COLOR, "-foreground", NULL, NULL,
74 DEF_CANVBMAP_FG, Tk_Offset(BitmapItem, fgColor), 0, NULL},
75 {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
76 NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
78 {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
79 NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
80 {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
84 * Prototypes for functions defined in this file:
87 static int BitmapCoords(Tcl_Interp *interp,
88 Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
89 Tcl_Obj *const objv[]);
90 static int BitmapToArea(Tk_Canvas canvas,
91 Tk_Item *itemPtr, double *rectPtr);
92 static double BitmapToPoint(Tk_Canvas canvas,
93 Tk_Item *itemPtr, double *coordPtr);
94 static int BitmapToPostscript(Tcl_Interp *interp,
95 Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
96 static void ComputeBitmapBbox(Tk_Canvas canvas,
98 static int ConfigureBitmap(Tcl_Interp *interp,
99 Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
100 Tcl_Obj *const objv[], int flags);
101 static int TkcCreateBitmap(Tcl_Interp *interp,
102 Tk_Canvas canvas, struct Tk_Item *itemPtr,
103 int objc, Tcl_Obj *const objv[]);
104 static void DeleteBitmap(Tk_Canvas canvas,
105 Tk_Item *itemPtr, Display *display);
106 static void DisplayBitmap(Tk_Canvas canvas,
107 Tk_Item *itemPtr, Display *display, Drawable dst,
108 int x, int y, int width, int height);
109 static void ScaleBitmap(Tk_Canvas canvas,
110 Tk_Item *itemPtr, double originX, double originY,
111 double scaleX, double scaleY);
112 static void TranslateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr,
113 double deltaX, double deltaY);
116 * The structures below defines the bitmap item type in terms of functions
117 * that can be invoked by generic item code.
120 Tk_ItemType tkBitmapType = {
122 sizeof(BitmapItem), /* itemSize */
123 TkcCreateBitmap, /* createProc */
124 configSpecs, /* configSpecs */
125 ConfigureBitmap, /* configureProc */
126 BitmapCoords, /* coordProc */
127 DeleteBitmap, /* deleteProc */
128 DisplayBitmap, /* displayProc */
129 TK_CONFIG_OBJS, /* flags */
130 BitmapToPoint, /* pointProc */
131 BitmapToArea, /* areaProc */
132 BitmapToPostscript, /* postscriptProc */
133 ScaleBitmap, /* scaleProc */
134 TranslateBitmap, /* translateProc */
135 NULL, /* indexProc */
136 NULL, /* icursorProc */
137 NULL, /* selectionProc */
138 NULL, /* insertProc */
139 NULL, /* dTextProc */
145 *--------------------------------------------------------------
149 * This function is invoked to create a new bitmap item in a canvas.
152 * A standard Tcl return value. If an error occurred in creating the
153 * item, then an error message is left in the interp's result; in this
154 * case itemPtr is left uninitialized, so it can be safely freed by the
158 * A new bitmap item is created.
160 *--------------------------------------------------------------
165 Tcl_Interp *interp, /* Interpreter for error reporting. */
166 Tk_Canvas canvas, /* Canvas to hold new item. */
167 Tk_Item *itemPtr, /* Record to hold new item; header has been
168 * initialized by caller. */
169 int objc, /* Number of arguments in objv. */
170 Tcl_Obj *const objv[]) /* Arguments describing rectangle. */
172 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
176 Tcl_Panic("canvas did not pass any coords");
180 * Initialize item's record.
183 bmapPtr->anchor = TK_ANCHOR_CENTER;
184 bmapPtr->bitmap = None;
185 bmapPtr->activeBitmap = None;
186 bmapPtr->disabledBitmap = None;
187 bmapPtr->fgColor = NULL;
188 bmapPtr->activeFgColor = NULL;
189 bmapPtr->disabledFgColor = NULL;
190 bmapPtr->bgColor = NULL;
191 bmapPtr->activeBgColor = NULL;
192 bmapPtr->disabledBgColor = NULL;
196 * Process the arguments to fill in the item record. Only 1 (list) or 2 (x
197 * y) coords are allowed.
203 const char *arg = Tcl_GetString(objv[1]);
205 if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
209 if (BitmapCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
212 if (ConfigureBitmap(interp, canvas, itemPtr, objc-i, objv+i, 0)
218 DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
223 *--------------------------------------------------------------
227 * This function is invoked to process the "coords" widget command on
228 * bitmap items. See the user documentation for details on what it does.
231 * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
234 * The coordinates for the given item may be changed.
236 *--------------------------------------------------------------
241 Tcl_Interp *interp, /* Used for error reporting. */
242 Tk_Canvas canvas, /* Canvas containing item. */
243 Tk_Item *itemPtr, /* Item whose coordinates are to be read or
245 int objc, /* Number of coordinates supplied in objv. */
246 Tcl_Obj *const objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */
248 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
251 Tcl_Obj *obj = Tcl_NewObj();
253 Tcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bmapPtr->x));
254 Tcl_ListObjAppendElement(NULL, obj, Tcl_NewDoubleObj(bmapPtr->y));
255 Tcl_SetObjResult(interp, obj);
256 } else if (objc < 3) {
258 if (Tcl_ListObjGetElements(interp, objv[0], &objc,
259 (Tcl_Obj ***) &objv) != TCL_OK) {
261 } else if (objc != 2) {
262 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
263 "wrong # coordinates: expected 2, got %d", objc));
264 Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "BITMAP",
269 if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],
270 &bmapPtr->x) != TCL_OK)
271 || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
272 &bmapPtr->y) != TCL_OK)) {
275 ComputeBitmapBbox(canvas, bmapPtr);
277 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
278 "wrong # coordinates: expected 0 or 2, got %d", objc));
279 Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "BITMAP", NULL);
286 *--------------------------------------------------------------
290 * This function is invoked to configure various aspects of a bitmap
291 * item, such as its anchor position.
294 * A standard Tcl result code. If an error occurs, then an error message
295 * is left in the interp's result.
298 * Configuration information may be set for itemPtr.
300 *--------------------------------------------------------------
305 Tcl_Interp *interp, /* Used for error reporting. */
306 Tk_Canvas canvas, /* Canvas containing itemPtr. */
307 Tk_Item *itemPtr, /* Bitmap item to reconfigure. */
308 int objc, /* Number of elements in objv. */
309 Tcl_Obj *const objv[], /* Arguments describing things to configure. */
310 int flags) /* Flags to pass to Tk_ConfigureWidget. */
312 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
322 tkwin = Tk_CanvasTkwin(canvas);
323 if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
324 (const char **) objv, (char *) bmapPtr, flags|TK_CONFIG_OBJS)) {
329 * A few of the options require additional processing, such as those that
330 * determine the graphics context.
333 state = itemPtr->state;
335 if (bmapPtr->activeFgColor!=NULL ||
336 bmapPtr->activeBgColor!=NULL ||
337 bmapPtr->activeBitmap!=None) {
338 itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
340 itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
343 if (state == TK_STATE_NULL) {
344 state = Canvas(canvas)->canvas_state;
346 if (state == TK_STATE_HIDDEN) {
347 ComputeBitmapBbox(canvas, bmapPtr);
350 fgColor = bmapPtr->fgColor;
351 bgColor = bmapPtr->bgColor;
352 bitmap = bmapPtr->bitmap;
353 if (Canvas(canvas)->currentItemPtr == itemPtr) {
354 if (bmapPtr->activeFgColor!=NULL) {
355 fgColor = bmapPtr->activeFgColor;
357 if (bmapPtr->activeBgColor!=NULL) {
358 bgColor = bmapPtr->activeBgColor;
360 if (bmapPtr->activeBitmap!=None) {
361 bitmap = bmapPtr->activeBitmap;
363 } else if (state == TK_STATE_DISABLED) {
364 if (bmapPtr->disabledFgColor!=NULL) {
365 fgColor = bmapPtr->disabledFgColor;
367 if (bmapPtr->disabledBgColor!=NULL) {
368 bgColor = bmapPtr->disabledBgColor;
370 if (bmapPtr->disabledBitmap!=None) {
371 bitmap = bmapPtr->disabledBitmap;
375 if (bitmap == None) {
378 gcValues.foreground = fgColor->pixel;
380 if (bgColor != NULL) {
381 gcValues.background = bgColor->pixel;
382 mask |= GCBackground;
384 gcValues.clip_mask = bitmap;
387 newGC = Tk_GetGC(tkwin, mask, &gcValues);
389 if (bmapPtr->gc != NULL) {
390 Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
394 ComputeBitmapBbox(canvas, bmapPtr);
399 *--------------------------------------------------------------
403 * This function is called to clean up the data structure associated with
410 * Resources associated with itemPtr are released.
412 *--------------------------------------------------------------
417 Tk_Canvas canvas, /* Info about overall canvas widget. */
418 Tk_Item *itemPtr, /* Item that is being deleted. */
419 Display *display) /* Display containing window for canvas. */
421 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
423 if (bmapPtr->bitmap != None) {
424 Tk_FreeBitmap(display, bmapPtr->bitmap);
426 if (bmapPtr->activeBitmap != None) {
427 Tk_FreeBitmap(display, bmapPtr->activeBitmap);
429 if (bmapPtr->disabledBitmap != None) {
430 Tk_FreeBitmap(display, bmapPtr->disabledBitmap);
432 if (bmapPtr->fgColor != NULL) {
433 Tk_FreeColor(bmapPtr->fgColor);
435 if (bmapPtr->activeFgColor != NULL) {
436 Tk_FreeColor(bmapPtr->activeFgColor);
438 if (bmapPtr->disabledFgColor != NULL) {
439 Tk_FreeColor(bmapPtr->disabledFgColor);
441 if (bmapPtr->bgColor != NULL) {
442 Tk_FreeColor(bmapPtr->bgColor);
444 if (bmapPtr->activeBgColor != NULL) {
445 Tk_FreeColor(bmapPtr->activeBgColor);
447 if (bmapPtr->disabledBgColor != NULL) {
448 Tk_FreeColor(bmapPtr->disabledBgColor);
450 if (bmapPtr->gc != NULL) {
451 Tk_FreeGC(display, bmapPtr->gc);
456 *--------------------------------------------------------------
458 * ComputeBitmapBbox --
460 * This function is invoked to compute the bounding box of all the pixels
461 * that may be drawn as part of a bitmap item. This function is where the
462 * child bitmap's placement is computed.
468 * The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
470 *--------------------------------------------------------------
476 Tk_Canvas canvas, /* Canvas that contains item. */
477 BitmapItem *bmapPtr) /* Item whose bbox is to be recomputed. */
482 Tk_State state = bmapPtr->header.state;
484 if (state == TK_STATE_NULL) {
485 state = Canvas(canvas)->canvas_state;
487 bitmap = bmapPtr->bitmap;
488 if (Canvas(canvas)->currentItemPtr == (Tk_Item *)bmapPtr) {
489 if (bmapPtr->activeBitmap!=None) {
490 bitmap = bmapPtr->activeBitmap;
492 } else if (state==TK_STATE_DISABLED) {
493 if (bmapPtr->disabledBitmap!=None) {
494 bitmap = bmapPtr->disabledBitmap;
498 x = (int) (bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5));
499 y = (int) (bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5));
501 if (state==TK_STATE_HIDDEN || bitmap == None) {
502 bmapPtr->header.x1 = bmapPtr->header.x2 = x;
503 bmapPtr->header.y1 = bmapPtr->header.y2 = y;
508 * Compute location and size of bitmap, using anchor information.
511 Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,
513 switch (bmapPtr->anchor) {
540 case TK_ANCHOR_CENTER:
547 * Store the information in the item header.
550 bmapPtr->header.x1 = x;
551 bmapPtr->header.y1 = y;
552 bmapPtr->header.x2 = x + width;
553 bmapPtr->header.y2 = y + height;
557 *--------------------------------------------------------------
561 * This function is invoked to draw a bitmap item in a given drawable.
567 * ItemPtr is drawn in drawable using the transformation information in
570 *--------------------------------------------------------------
575 Tk_Canvas canvas, /* Canvas that contains item. */
576 Tk_Item *itemPtr, /* Item to be displayed. */
577 Display *display, /* Display on which to draw item. */
578 Drawable drawable, /* Pixmap or window in which to draw item. */
579 int x, int y, int width, int height)
580 /* Describes region of canvas that must be
581 * redisplayed (not used). */
583 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
584 int bmapX, bmapY, bmapWidth, bmapHeight;
585 short drawableX, drawableY;
587 Tk_State state = itemPtr->state;
590 * If the area being displayed doesn't cover the whole bitmap, then only
591 * redisplay the part of the bitmap that needs redisplay.
594 if (state == TK_STATE_NULL) {
595 state = Canvas(canvas)->canvas_state;
597 bitmap = bmapPtr->bitmap;
598 if (Canvas(canvas)->currentItemPtr == itemPtr) {
599 if (bmapPtr->activeBitmap!=None) {
600 bitmap = bmapPtr->activeBitmap;
602 } else if (state == TK_STATE_DISABLED) {
603 if (bmapPtr->disabledBitmap!=None) {
604 bitmap = bmapPtr->disabledBitmap;
608 if (bitmap != None) {
609 if (x > bmapPtr->header.x1) {
610 bmapX = x - bmapPtr->header.x1;
611 bmapWidth = bmapPtr->header.x2 - x;
614 if ((x+width) < bmapPtr->header.x2) {
615 bmapWidth = x + width - bmapPtr->header.x1;
617 bmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1;
620 if (y > bmapPtr->header.y1) {
621 bmapY = y - bmapPtr->header.y1;
622 bmapHeight = bmapPtr->header.y2 - y;
625 if ((y+height) < bmapPtr->header.y2) {
626 bmapHeight = y + height - bmapPtr->header.y1;
628 bmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1;
631 Tk_CanvasDrawableCoords(canvas,
632 (double) (bmapPtr->header.x1 + bmapX),
633 (double) (bmapPtr->header.y1 + bmapY),
634 &drawableX, &drawableY);
637 * Must modify the mask origin within the graphics context to line up
638 * with the bitmap's origin (in order to make bitmaps with
639 * "-background {}" work right).
642 XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,
644 XCopyPlane(display, bitmap, drawable,
645 bmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth,
646 (unsigned int) bmapHeight, drawableX, drawableY, 1);
647 XSetClipOrigin(display, bmapPtr->gc, 0, 0);
652 *--------------------------------------------------------------
656 * Computes the distance from a given point to a given rectangle, in
660 * The return value is 0 if the point whose x and y coordinates are
661 * coordPtr[0] and coordPtr[1] is inside the bitmap. If the point isn't
662 * inside the bitmap then the return value is the distance from the point
668 *--------------------------------------------------------------
674 Tk_Canvas canvas, /* Canvas containing item. */
675 Tk_Item *itemPtr, /* Item to check against point. */
676 double *coordPtr) /* Pointer to x and y coordinates. */
678 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
679 double x1, x2, y1, y2, xDiff, yDiff;
681 x1 = bmapPtr->header.x1;
682 y1 = bmapPtr->header.y1;
683 x2 = bmapPtr->header.x2;
684 y2 = bmapPtr->header.y2;
687 * Point is outside rectangle.
690 if (coordPtr[0] < x1) {
691 xDiff = x1 - coordPtr[0];
692 } else if (coordPtr[0] > x2) {
693 xDiff = coordPtr[0] - x2;
698 if (coordPtr[1] < y1) {
699 yDiff = y1 - coordPtr[1];
700 } else if (coordPtr[1] > y2) {
701 yDiff = coordPtr[1] - y2;
706 return hypot(xDiff, yDiff);
710 *--------------------------------------------------------------
714 * This function is called to determine whether an item lies entirely
715 * inside, entirely outside, or overlapping a given rectangle.
718 * -1 is returned if the item is entirely outside the area given by
719 * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given
725 *--------------------------------------------------------------
731 Tk_Canvas canvas, /* Canvas containing item. */
732 Tk_Item *itemPtr, /* Item to check against rectangle. */
733 double *rectPtr) /* Pointer to array of four coordinates
734 * (x1,y1,x2,y2) describing rectangular
737 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
739 if ((rectPtr[2] <= bmapPtr->header.x1)
740 || (rectPtr[0] >= bmapPtr->header.x2)
741 || (rectPtr[3] <= bmapPtr->header.y1)
742 || (rectPtr[1] >= bmapPtr->header.y2)) {
745 if ((rectPtr[0] <= bmapPtr->header.x1)
746 && (rectPtr[1] <= bmapPtr->header.y1)
747 && (rectPtr[2] >= bmapPtr->header.x2)
748 && (rectPtr[3] >= bmapPtr->header.y2)) {
755 *--------------------------------------------------------------
759 * This function is invoked to rescale a bitmap item in a canvas. It is
760 * one of the standard item functions for bitmap items, and is invoked by
761 * the generic canvas code.
767 * The item referred to by itemPtr is rescaled so that the following
768 * transformation is applied to all point coordinates:
769 * x' = originX + scaleX*(x-originX)
770 * y' = originY + scaleY*(y-originY)
772 *--------------------------------------------------------------
777 Tk_Canvas canvas, /* Canvas containing rectangle. */
778 Tk_Item *itemPtr, /* Rectangle to be scaled. */
779 double originX, double originY,
780 /* Origin about which to scale item. */
781 double scaleX, /* Amount to scale in X direction. */
782 double scaleY) /* Amount to scale in Y direction. */
784 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
786 bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);
787 bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);
788 ComputeBitmapBbox(canvas, bmapPtr);
792 *--------------------------------------------------------------
796 * This function is called to move an item by a given amount.
802 * The position of the item is offset by (xDelta, yDelta), and the
803 * bounding box is updated in the generic part of the item structure.
805 *--------------------------------------------------------------
810 Tk_Canvas canvas, /* Canvas containing item. */
811 Tk_Item *itemPtr, /* Item that is being moved. */
812 double deltaX, double deltaY)
813 /* Amount by which item is to be moved. */
815 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
817 bmapPtr->x += deltaX;
818 bmapPtr->y += deltaY;
819 ComputeBitmapBbox(canvas, bmapPtr);
823 *--------------------------------------------------------------
825 * BitmapToPostscript --
827 * This function is called to generate Postscript for bitmap items.
830 * The return value is a standard Tcl result. If an error occurs in
831 * generating Postscript then an error message is left in the interp's
832 * result, replacing whatever used to be there. If no error occurs, then
833 * Postscript for the item is appended to the result.
838 *--------------------------------------------------------------
843 Tcl_Interp *interp, /* Leave Postscript or error message here. */
844 Tk_Canvas canvas, /* Information about overall canvas. */
845 Tk_Item *itemPtr, /* Item for which Postscript is wanted. */
846 int prepass) /* 1 means this is a prepass to collect font
847 * information; 0 means final Postscript is
850 BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
852 int width, height, rowsAtOnce, rowsThisTime;
857 Tk_State state = itemPtr->state;
859 Tcl_InterpState interpState;
861 if (state == TK_STATE_NULL) {
862 state = Canvas(canvas)->canvas_state;
864 fgColor = bmapPtr->fgColor;
865 bgColor = bmapPtr->bgColor;
866 bitmap = bmapPtr->bitmap;
867 if (Canvas(canvas)->currentItemPtr == itemPtr) {
868 if (bmapPtr->activeFgColor!=NULL) {
869 fgColor = bmapPtr->activeFgColor;
871 if (bmapPtr->activeBgColor!=NULL) {
872 bgColor = bmapPtr->activeBgColor;
874 if (bmapPtr->activeBitmap!=None) {
875 bitmap = bmapPtr->activeBitmap;
877 } else if (state == TK_STATE_DISABLED) {
878 if (bmapPtr->disabledFgColor!=NULL) {
879 fgColor = bmapPtr->disabledFgColor;
881 if (bmapPtr->disabledBgColor!=NULL) {
882 bgColor = bmapPtr->disabledBgColor;
884 if (bmapPtr->disabledBitmap!=None) {
885 bitmap = bmapPtr->disabledBitmap;
889 if (bitmap == None) {
894 * Compute the coordinates of the lower-left corner of the bitmap, taking
895 * into account the anchor position for the bitmp.
899 y = Tk_CanvasPsY(canvas, bmapPtr->y);
900 Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,
902 switch (bmapPtr->anchor) {
903 case TK_ANCHOR_NW: y -= height; break;
904 case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
905 case TK_ANCHOR_NE: x -= width; y -= height; break;
906 case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
907 case TK_ANCHOR_SE: x -= width; break;
908 case TK_ANCHOR_S: x -= width/2.0; break;
909 case TK_ANCHOR_SW: break;
910 case TK_ANCHOR_W: y -= height/2.0; break;
911 case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
915 * Make our working space.
918 psObj = Tcl_NewObj();
919 interpState = Tcl_SaveInterpState(interp, TCL_OK);
922 * Color the background, if there is one.
925 if (bgColor != NULL) {
926 Tcl_AppendPrintfToObj(psObj,
927 "%.15g %.15g moveto %d 0 rlineto 0 %d rlineto "
928 "%d 0 rlineto closepath\n",
929 x, y, width, height, -width);
931 Tcl_ResetResult(interp);
932 if (Tk_CanvasPsColor(interp, canvas, bgColor) != TCL_OK) {
935 Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
937 Tcl_AppendToObj(psObj, "fill\n", -1);
941 * Draw the bitmap, if there is a foreground color. If the bitmap is very
942 * large, then chop it up into multiple bitmaps, each consisting of one or
943 * more rows. This is needed because Postscript can't handle single
944 * strings longer than 64 KBytes long.
947 if (fgColor != NULL) {
948 Tcl_ResetResult(interp);
949 if (Tk_CanvasPsColor(interp, canvas, fgColor) != TCL_OK) {
952 Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
955 Tcl_SetObjResult(interp, Tcl_NewStringObj(
956 "can't generate Postscript for bitmaps more than 60000"
957 " pixels wide", -1));
958 Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "MEMLIMIT", NULL);
962 rowsAtOnce = 60000/width;
963 if (rowsAtOnce < 1) {
967 Tcl_AppendPrintfToObj(psObj, "%.15g %.15g translate\n", x, y+height);
969 for (curRow = 0; curRow < height; curRow += rowsAtOnce) {
970 rowsThisTime = rowsAtOnce;
971 if (rowsThisTime > (height - curRow)) {
972 rowsThisTime = height - curRow;
975 Tcl_AppendPrintfToObj(psObj,
976 "0 -%.15g translate\n%d %d true matrix {\n",
977 (double) rowsThisTime, width, rowsThisTime);
979 Tcl_ResetResult(interp);
980 if (Tk_CanvasPsBitmap(interp, canvas, bitmap,
981 0, curRow, width, rowsThisTime) != TCL_OK) {
984 Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
986 Tcl_AppendToObj(psObj, "\n} imagemask\n", -1);
991 * Plug the accumulated postscript back into the result.
994 (void) Tcl_RestoreInterpState(interp, interpState);
995 Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
996 Tcl_DecrRefCount(psObj);
1000 Tcl_DiscardInterpState(interpState);
1001 Tcl_DecrRefCount(psObj);