4 * This file implements bitmap items for canvas widgets.
6 * Copyright 1992 Regents of the University of California.
7 * Permission to use, copy, modify, and distribute this
8 * software and its documentation for any purpose and without
9 * fee is hereby granted, provided that the above copyright
10 * notice appear in all copies. The University of California
11 * makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without
13 * express or implied warranty.
17 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkCanvBmap.c,v 1.4 92/08/24 09:24:11 ouster Exp $ SPRITE (Berkeley)";
26 * The structure below defines the record for each rectangle/oval item.
29 typedef struct BitmapItem
{
30 Tk_Item header
; /* Generic stuff that's the same for all
31 * types. MUST BE FIRST IN STRUCTURE. */
32 double x
, y
; /* Coordinates of positioning point for
34 Tk_Anchor anchor
; /* Where to anchor bitmap relative to
36 Pixmap bitmap
; /* Bitmap to display in window. */
37 XColor
*fgColor
; /* Foreground color to use for bitmap. */
38 XColor
*bgColor
; /* Background color to use for bitmap. */
39 GC gc
; /* Graphics context to use for drawing
40 * bitmap on screen. */
44 * Information used for parsing configuration specs:
47 static Tk_ConfigSpec configSpecs
[] = {
48 {TK_CONFIG_ANCHOR
, "-anchor", (char *) NULL
, (char *) NULL
,
49 "center", Tk_Offset(BitmapItem
, anchor
), TK_CONFIG_DONT_SET_DEFAULT
},
50 {TK_CONFIG_COLOR
, "-background", (char *) NULL
, (char *) NULL
,
51 (char *) NULL
, Tk_Offset(BitmapItem
, bgColor
), TK_CONFIG_NULL_OK
},
53 {TK_CONFIG_PIXMAP
, "-bitmap", (char *) NULL
, (char *) NULL
,
54 (char *) NULL
, Tk_Offset(BitmapItem
, bitmap
), TK_CONFIG_NULL_OK
},
56 {TK_CONFIG_BITMAP
, "-bitmap", (char *) NULL
, (char *) NULL
,
57 (char *) NULL
, Tk_Offset(BitmapItem
, bitmap
), TK_CONFIG_NULL_OK
},
59 {TK_CONFIG_COLOR
, "-foreground", (char *) NULL
, (char *) NULL
,
60 "black", Tk_Offset(BitmapItem
, fgColor
), 0},
61 {TK_CONFIG_CUSTOM
, "-tags", (char *) NULL
, (char *) NULL
,
62 (char *) NULL
, 0, TK_CONFIG_NULL_OK
, &tkCanvasTagsOption
},
63 {TK_CONFIG_END
, (char *) NULL
, (char *) NULL
, (char *) NULL
,
68 * Prototypes for procedures defined in this file:
71 static int BitmapCoords
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
72 Tk_Item
*itemPtr
, int argc
, char **argv
));
73 static int BitmapToArea
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
74 Tk_Item
*itemPtr
, double *rectPtr
));
75 static double BitmapToPoint
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
76 Tk_Item
*itemPtr
, double *coordPtr
));
77 static void ComputeBitmapBbox
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
78 BitmapItem
*bmapPtr
));
79 static int ConfigureBitmap
_ANSI_ARGS_((
80 Tk_Canvas
*canvasPtr
, Tk_Item
*itemPtr
, int argc
,
81 char **argv
, int flags
));
82 static int CreateBitmap
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
83 struct Tk_Item
*itemPtr
, int argc
, char **argv
));
84 static void DeleteBitmap
_ANSI_ARGS_((Tk_Item
*itemPtr
));
85 static void DisplayBitmap
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
86 Tk_Item
*itemPtr
, Drawable dst
));
87 static void ScaleBitmap
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
88 Tk_Item
*itemPtr
, double originX
, double originY
,
89 double scaleX
, double scaleY
));
90 static void TranslateBitmap
_ANSI_ARGS_((Tk_Canvas
*canvasPtr
,
91 Tk_Item
*itemPtr
, double deltaX
, double deltaY
));
94 * The structures below defines the rectangle and oval item types
95 * by means of procedures that can be invoked by generic item code.
98 Tk_ItemType TkBitmapType
= {
100 sizeof(BitmapItem
), /* itemSize */
101 CreateBitmap
, /* createProc */
102 configSpecs
, /* configSpecs */
103 ConfigureBitmap
, /* configureProc */
104 BitmapCoords
, /* coordProc */
105 DeleteBitmap
, /* deleteProc */
106 DisplayBitmap
, /* displayProc */
107 0, /* alwaysRedraw */
108 BitmapToPoint
, /* pointProc */
109 BitmapToArea
, /* areaProc */
110 (Tk_ItemPostscriptProc
*) NULL
, /* postscriptProc */
111 ScaleBitmap
, /* scaleProc */
112 TranslateBitmap
, /* translateProc */
113 (Tk_ItemIndexProc
*) NULL
, /* indexProc */
114 (Tk_ItemCursorProc
*) NULL
, /* cursorProc */
115 (Tk_ItemSelectionProc
*) NULL
, /* selectionProc */
116 (Tk_ItemInsertProc
*) NULL
, /* insertProc */
117 (Tk_ItemDCharsProc
*) NULL
, /* dTextProc */
118 (Tk_ItemType
*) NULL
/* nextPtr */
122 *--------------------------------------------------------------
126 * This procedure is invoked to create a new bitmap
130 * A standard Tcl return value. If an error occurred in
131 * creating the item, then an error message is left in
132 * canvasPtr->interp->result; in this case itemPtr is
133 * left uninitialized, so it can be safely freed by the
137 * A new bitmap item is created.
139 *--------------------------------------------------------------
143 CreateBitmap(canvasPtr
, itemPtr
, argc
, argv
)
144 register Tk_Canvas
*canvasPtr
; /* Canvas to hold new item. */
145 Tk_Item
*itemPtr
; /* Record to hold new item; header
146 * has been initialized by caller. */
147 int argc
; /* Number of arguments in argv. */
148 char **argv
; /* Arguments describing rectangle. */
150 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
153 Tcl_AppendResult(canvasPtr
->interp
, "wrong # args: should be \"",
154 Tk_PathName(canvasPtr
->tkwin
), "\" create ",
155 itemPtr
->typePtr
->name
, " x y ?options?",
161 * Initialize item's record.
164 bmapPtr
->anchor
= TK_ANCHOR_CENTER
;
165 bmapPtr
->bitmap
= None
;
166 bmapPtr
->fgColor
= NULL
;
167 bmapPtr
->bgColor
= NULL
;
171 * Process the arguments to fill in the item record.
174 if ((TkGetCanvasCoord(canvasPtr
, argv
[0], &bmapPtr
->x
) != TCL_OK
)
175 || (TkGetCanvasCoord(canvasPtr
, argv
[1],
176 &bmapPtr
->y
) != TCL_OK
)) {
180 if (ConfigureBitmap(canvasPtr
, itemPtr
, argc
-2, argv
+2, 0) != TCL_OK
) {
181 DeleteBitmap(itemPtr
);
188 *--------------------------------------------------------------
192 * This procedure is invoked to process the "coords" widget
193 * command on bitmap items. See the user documentation for
194 * details on what it does.
197 * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
200 * The coordinates for the given item may be changed.
202 *--------------------------------------------------------------
206 BitmapCoords(canvasPtr
, itemPtr
, argc
, argv
)
207 register Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
208 Tk_Item
*itemPtr
; /* Item whose coordinates are to be
209 * read or modified. */
210 int argc
; /* Number of coordinates supplied in
212 char **argv
; /* Array of coordinates: x1, y1,
215 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
218 sprintf(canvasPtr
->interp
->result
, "%g %g", bmapPtr
->x
, bmapPtr
->y
);
219 } else if (argc
== 2) {
220 if ((TkGetCanvasCoord(canvasPtr
, argv
[0], &bmapPtr
->x
) != TCL_OK
)
221 || (TkGetCanvasCoord(canvasPtr
, argv
[1],
222 &bmapPtr
->y
) != TCL_OK
)) {
225 ComputeBitmapBbox(canvasPtr
, bmapPtr
);
227 sprintf(canvasPtr
->interp
->result
,
228 "wrong # coordinates: expected 0 or 2, got %d",
236 *--------------------------------------------------------------
240 * This procedure is invoked to configure various aspects
241 * of a bitmap item, such as its anchor position.
244 * A standard Tcl result code. If an error occurs, then
245 * an error message is left in canvasPtr->interp->result.
248 * Configuration information may be set for itemPtr.
250 *--------------------------------------------------------------
254 ConfigureBitmap(canvasPtr
, itemPtr
, argc
, argv
, flags
)
255 Tk_Canvas
*canvasPtr
; /* Canvas containing itemPtr. */
256 Tk_Item
*itemPtr
; /* Bitmap item to reconfigure. */
257 int argc
; /* Number of elements in argv. */
258 char **argv
; /* Arguments describing things to configure. */
259 int flags
; /* Flags to pass to Tk_ConfigureWidget. */
261 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
265 if (Tk_ConfigureWidget(canvasPtr
->interp
, canvasPtr
->tkwin
,
266 configSpecs
, argc
, argv
, (char *) bmapPtr
, flags
) != TCL_OK
) {
271 * A few of the options require additional processing, such as those
272 * that determine the graphics context.
275 gcValues
.foreground
= bmapPtr
->fgColor
->pixel
;
276 if (bmapPtr
->bgColor
!= NULL
) {
277 gcValues
.background
= bmapPtr
->bgColor
->pixel
;
279 gcValues
.background
= canvasPtr
->bgColor
->pixel
;
281 newGC
= Tk_GetGC(canvasPtr
->tkwin
, GCForeground
|GCBackground
, &gcValues
);
282 if (bmapPtr
->gc
!= None
) {
283 Tk_FreeGC(bmapPtr
->gc
);
287 ComputeBitmapBbox(canvasPtr
, bmapPtr
);
293 *--------------------------------------------------------------
297 * This procedure is called to clean up the data structure
298 * associated with a bitmap item.
304 * Resources associated with itemPtr are released.
306 *--------------------------------------------------------------
310 DeleteBitmap(itemPtr
)
311 Tk_Item
*itemPtr
; /* Item that is being deleted. */
313 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
315 if (bmapPtr
->bitmap
!= None
) {
316 #if defined(USE_XPM3)
317 Tk_FreePixmap(bmapPtr
->bitmap
);
319 Tk_FreeBitmap(bmapPtr
->bitmap
);
322 if (bmapPtr
->fgColor
!= NULL
) {
323 Tk_FreeColor(bmapPtr
->fgColor
);
325 if (bmapPtr
->bgColor
!= NULL
) {
326 Tk_FreeColor(bmapPtr
->bgColor
);
328 if (bmapPtr
->gc
!= NULL
) {
329 Tk_FreeGC(bmapPtr
->gc
);
334 *--------------------------------------------------------------
336 * ComputeBitmapBbox --
338 * This procedure is invoked to compute the bounding box of
339 * all the pixels that may be drawn as part of a bitmap item.
340 * This procedure is where the child bitmap's placement is
347 * The fields x1, y1, x2, and y2 are updated in the header
350 *--------------------------------------------------------------
355 ComputeBitmapBbox(canvasPtr
, bmapPtr
)
356 Tk_Canvas
*canvasPtr
; /* Canvas that contains item. */
357 register BitmapItem
*bmapPtr
; /* Item whose bbox is to be
360 unsigned int width
, height
;
363 x
= bmapPtr
->x
+ 0.5;
364 y
= bmapPtr
->y
+ 0.5;
366 if (bmapPtr
->bitmap
== None
) {
367 bmapPtr
->header
.x1
= bmapPtr
->header
.x2
= x
;
368 bmapPtr
->header
.y1
= bmapPtr
->header
.y2
= y
;
373 * Compute location and size of bitmap, using anchor information.
376 #if defined(USE_XPM3)
377 Tk_SizeOfPixmap(bmapPtr
->bitmap
, &width
, &height
);
379 Tk_SizeOfBitmap(bmapPtr
->bitmap
, &width
, &height
);
381 switch (bmapPtr
->anchor
) {
408 case TK_ANCHOR_CENTER
:
415 * Store the information in the item header.
418 bmapPtr
->header
.x1
= x
;
419 bmapPtr
->header
.y1
= y
;
420 bmapPtr
->header
.x2
= x
+ width
;
421 bmapPtr
->header
.y2
= y
+ height
;
425 *--------------------------------------------------------------
429 * This procedure is invoked to draw a bitmap item in a given
436 * ItemPtr is drawn in drawable using the transformation
437 * information in canvasPtr.
439 *--------------------------------------------------------------
443 DisplayBitmap(canvasPtr
, itemPtr
, drawable
)
444 register Tk_Canvas
*canvasPtr
; /* Canvas that contains item. */
445 Tk_Item
*itemPtr
; /* Item to be displayed. */
446 Drawable drawable
; /* Pixmap or window in which to draw
449 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
451 if (bmapPtr
->bitmap
!= None
) {
452 #if defined(USE_XPM3)
453 XCopyArea(Tk_Display(canvasPtr
->tkwin
), bmapPtr
->bitmap
, drawable
,
455 (unsigned int) bmapPtr
->header
.x2
- bmapPtr
->header
.x1
,
456 (unsigned int) bmapPtr
->header
.y2
- bmapPtr
->header
.y1
,
457 bmapPtr
->header
.x1
- canvasPtr
->drawableXOrigin
,
458 bmapPtr
->header
.y1
- canvasPtr
->drawableYOrigin
);
460 XCopyPlane(Tk_Display(canvasPtr
->tkwin
), bmapPtr
->bitmap
, drawable
,
462 (unsigned int) bmapPtr
->header
.x2
- bmapPtr
->header
.x1
,
463 (unsigned int) bmapPtr
->header
.y2
- bmapPtr
->header
.y1
,
464 bmapPtr
->header
.x1
- canvasPtr
->drawableXOrigin
,
465 bmapPtr
->header
.y1
- canvasPtr
->drawableYOrigin
, 1);
471 *--------------------------------------------------------------
475 * Computes the distance from a given point to a given
476 * rectangle, in canvas units.
479 * The return value is 0 if the point whose x and y coordinates
480 * are coordPtr[0] and coordPtr[1] is inside the bitmap. If the
481 * point isn't inside the bitmap then the return value is the
482 * distance from the point to the bitmap.
487 *--------------------------------------------------------------
492 BitmapToPoint(canvasPtr
, itemPtr
, coordPtr
)
493 Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
494 Tk_Item
*itemPtr
; /* Item to check against point. */
495 double *coordPtr
; /* Pointer to x and y coordinates. */
497 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
498 double x1
, x2
, y1
, y2
, xDiff
, yDiff
;
500 x1
= bmapPtr
->header
.x1
;
501 y1
= bmapPtr
->header
.y1
;
502 x2
= bmapPtr
->header
.x2
;
503 y2
= bmapPtr
->header
.y2
;
506 * Point is outside rectangle.
509 if (coordPtr
[0] < x1
) {
510 xDiff
= x1
- coordPtr
[0];
511 } else if (coordPtr
[0] > x2
) {
512 xDiff
= coordPtr
[0] - x2
;
517 if (coordPtr
[1] < y1
) {
518 yDiff
= y1
- coordPtr
[1];
519 } else if (coordPtr
[1] > y2
) {
520 yDiff
= coordPtr
[1] - y2
;
525 return hypot(xDiff
, yDiff
);
529 *--------------------------------------------------------------
533 * This procedure is called to determine whether an item
534 * lies entirely inside, entirely outside, or overlapping
538 * -1 is returned if the item is entirely outside the area
539 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
540 * inside the given area.
545 *--------------------------------------------------------------
550 BitmapToArea(canvasPtr
, itemPtr
, rectPtr
)
551 Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
552 Tk_Item
*itemPtr
; /* Item to check against rectangle. */
553 double *rectPtr
; /* Pointer to array of four coordinates
554 * (x1, y1, x2, y2) describing rectangular
557 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
559 if ((rectPtr
[2] <= bmapPtr
->header
.x1
)
560 || (rectPtr
[0] >= bmapPtr
->header
.x2
)
561 || (rectPtr
[3] <= bmapPtr
->header
.y1
)
562 || (rectPtr
[1] >= bmapPtr
->header
.y2
)) {
565 if ((rectPtr
[0] <= bmapPtr
->header
.x1
)
566 && (rectPtr
[1] <= bmapPtr
->header
.y1
)
567 && (rectPtr
[2] >= bmapPtr
->header
.x2
)
568 && (rectPtr
[3] >= bmapPtr
->header
.y2
)) {
575 *--------------------------------------------------------------
579 * This procedure is invoked to rescale a rectangle or oval
586 * The rectangle or oval referred to by itemPtr is rescaled
587 * so that the following transformation is applied to all
589 * x' = originX + scaleX*(x-originX)
590 * y' = originY + scaleY*(y-originY)
592 *--------------------------------------------------------------
596 ScaleBitmap(canvasPtr
, itemPtr
, originX
, originY
, scaleX
, scaleY
)
597 Tk_Canvas
*canvasPtr
; /* Canvas containing rectangle. */
598 Tk_Item
*itemPtr
; /* Rectangle to be scaled. */
599 double originX
, originY
; /* Origin about which to scale rect. */
600 double scaleX
; /* Amount to scale in X direction. */
601 double scaleY
; /* Amount to scale in Y direction. */
603 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
605 bmapPtr
->x
= originX
+ scaleX
*(bmapPtr
->x
- originX
);
606 bmapPtr
->y
= originY
+ scaleY
*(bmapPtr
->y
- originY
);
607 ComputeBitmapBbox(canvasPtr
, bmapPtr
);
611 *--------------------------------------------------------------
615 * This procedure is called to move a rectangle or oval by a
622 * The position of the rectangle or oval is offset by
623 * (xDelta, yDelta), and the bounding box is updated in the
624 * generic part of the item structure.
626 *--------------------------------------------------------------
630 TranslateBitmap(canvasPtr
, itemPtr
, deltaX
, deltaY
)
631 Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
632 Tk_Item
*itemPtr
; /* Item that is being moved. */
633 double deltaX
, deltaY
; /* Amount by which item is to be
636 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
638 bmapPtr
->x
+= deltaX
;
639 bmapPtr
->y
+= deltaY
;
640 ComputeBitmapBbox(canvasPtr
, bmapPtr
);