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 *--------------------------------------------------------------
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. */
151 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
154 Tcl_AppendResult(canvasPtr
->interp
, "wrong # args: should be \"",
155 Tk_PathName(canvasPtr
->tkwin
), "\" create ",
156 itemPtr
->typePtr
->name
, " x y ?options?",
162 * Initialize item's record.
165 bmapPtr
->anchor
= TK_ANCHOR_CENTER
;
166 bmapPtr
->bitmap
= None
;
167 bmapPtr
->fgColor
= NULL
;
168 bmapPtr
->bgColor
= NULL
;
172 * Process the arguments to fill in the item record.
175 if ((TkGetCanvasCoord(canvasPtr
, argv
[0], &bmapPtr
->x
) != TCL_OK
)
176 || (TkGetCanvasCoord(canvasPtr
, argv
[1],
177 &bmapPtr
->y
) != TCL_OK
)) {
181 if (ConfigureBitmap(canvasPtr
, itemPtr
, argc
-2, argv
+2, 0) != TCL_OK
) {
182 DeleteBitmap(itemPtr
);
189 *--------------------------------------------------------------
193 * This procedure is invoked to process the "coords" widget
194 * command on bitmap items. See the user documentation for
195 * details on what it does.
198 * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
201 * The coordinates for the given item may be changed.
203 *--------------------------------------------------------------
208 register Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
209 Tk_Item
*itemPtr
, /* Item whose coordinates are to be
210 * read or modified. */
211 int argc
, /* Number of coordinates supplied in
213 char **argv
/* Array of coordinates: x1, y1,
217 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
220 sprintf(canvasPtr
->interp
->result
, "%g %g", bmapPtr
->x
, bmapPtr
->y
);
221 } else if (argc
== 2) {
222 if ((TkGetCanvasCoord(canvasPtr
, argv
[0], &bmapPtr
->x
) != TCL_OK
)
223 || (TkGetCanvasCoord(canvasPtr
, argv
[1],
224 &bmapPtr
->y
) != TCL_OK
)) {
227 ComputeBitmapBbox(canvasPtr
, bmapPtr
);
229 sprintf(canvasPtr
->interp
->result
,
230 "wrong # coordinates: expected 0 or 2, got %d",
238 *--------------------------------------------------------------
242 * This procedure is invoked to configure various aspects
243 * of a bitmap item, such as its anchor position.
246 * A standard Tcl result code. If an error occurs, then
247 * an error message is left in canvasPtr->interp->result.
250 * Configuration information may be set for itemPtr.
252 *--------------------------------------------------------------
257 Tk_Canvas
*canvasPtr
, /* Canvas containing itemPtr. */
258 Tk_Item
*itemPtr
, /* Bitmap item to reconfigure. */
259 int argc
, /* Number of elements in argv. */
260 char **argv
, /* Arguments describing things to configure. */
261 int flags
/* Flags to pass to Tk_ConfigureWidget. */
264 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
268 if (Tk_ConfigureWidget(canvasPtr
->interp
, canvasPtr
->tkwin
,
269 configSpecs
, argc
, argv
, (char *) bmapPtr
, flags
) != TCL_OK
) {
274 * A few of the options require additional processing, such as those
275 * that determine the graphics context.
278 gcValues
.foreground
= bmapPtr
->fgColor
->pixel
;
279 if (bmapPtr
->bgColor
!= NULL
) {
280 gcValues
.background
= bmapPtr
->bgColor
->pixel
;
282 gcValues
.background
= canvasPtr
->bgColor
->pixel
;
284 newGC
= Tk_GetGC(canvasPtr
->tkwin
, GCForeground
|GCBackground
, &gcValues
);
285 if (bmapPtr
->gc
!= None
) {
286 Tk_FreeGC(bmapPtr
->gc
);
290 ComputeBitmapBbox(canvasPtr
, bmapPtr
);
296 *--------------------------------------------------------------
300 * This procedure is called to clean up the data structure
301 * associated with a bitmap item.
307 * Resources associated with itemPtr are released.
309 *--------------------------------------------------------------
314 Tk_Item
*itemPtr
/* Item that is being deleted. */
317 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
319 if (bmapPtr
->bitmap
!= None
) {
320 #if defined(USE_XPM3)
321 Tk_FreePixmap(bmapPtr
->bitmap
);
323 Tk_FreeBitmap(bmapPtr
->bitmap
);
326 if (bmapPtr
->fgColor
!= NULL
) {
327 Tk_FreeColor(bmapPtr
->fgColor
);
329 if (bmapPtr
->bgColor
!= NULL
) {
330 Tk_FreeColor(bmapPtr
->bgColor
);
332 if (bmapPtr
->gc
!= NULL
) {
333 Tk_FreeGC(bmapPtr
->gc
);
338 *--------------------------------------------------------------
340 * ComputeBitmapBbox --
342 * This procedure is invoked to compute the bounding box of
343 * all the pixels that may be drawn as part of a bitmap item.
344 * This procedure is where the child bitmap's placement is
351 * The fields x1, y1, x2, and y2 are updated in the header
354 *--------------------------------------------------------------
360 Tk_Canvas
*canvasPtr
, /* Canvas that contains item. */
361 register BitmapItem
*bmapPtr
/* Item whose bbox is to be
365 unsigned int width
, height
;
368 x
= bmapPtr
->x
+ 0.5;
369 y
= bmapPtr
->y
+ 0.5;
371 if (bmapPtr
->bitmap
== None
) {
372 bmapPtr
->header
.x1
= bmapPtr
->header
.x2
= x
;
373 bmapPtr
->header
.y1
= bmapPtr
->header
.y2
= y
;
378 * Compute location and size of bitmap, using anchor information.
381 #if defined(USE_XPM3)
382 Tk_SizeOfPixmap(bmapPtr
->bitmap
, &width
, &height
);
384 Tk_SizeOfBitmap(bmapPtr
->bitmap
, &width
, &height
);
386 switch (bmapPtr
->anchor
) {
413 case TK_ANCHOR_CENTER
:
420 * Store the information in the item header.
423 bmapPtr
->header
.x1
= x
;
424 bmapPtr
->header
.y1
= y
;
425 bmapPtr
->header
.x2
= x
+ width
;
426 bmapPtr
->header
.y2
= y
+ height
;
430 *--------------------------------------------------------------
434 * This procedure is invoked to draw a bitmap item in a given
441 * ItemPtr is drawn in drawable using the transformation
442 * information in canvasPtr.
444 *--------------------------------------------------------------
449 register Tk_Canvas
*canvasPtr
, /* Canvas that contains item. */
450 Tk_Item
*itemPtr
, /* Item to be displayed. */
451 Drawable drawable
/* Pixmap or window in which to draw
455 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
457 if (bmapPtr
->bitmap
!= None
) {
458 #if defined(USE_XPM3)
459 XCopyArea(Tk_Display(canvasPtr
->tkwin
), bmapPtr
->bitmap
, drawable
,
461 (unsigned int) bmapPtr
->header
.x2
- bmapPtr
->header
.x1
,
462 (unsigned int) bmapPtr
->header
.y2
- bmapPtr
->header
.y1
,
463 bmapPtr
->header
.x1
- canvasPtr
->drawableXOrigin
,
464 bmapPtr
->header
.y1
- canvasPtr
->drawableYOrigin
);
466 XCopyPlane(Tk_Display(canvasPtr
->tkwin
), bmapPtr
->bitmap
, drawable
,
468 (unsigned int) bmapPtr
->header
.x2
- bmapPtr
->header
.x1
,
469 (unsigned int) bmapPtr
->header
.y2
- bmapPtr
->header
.y1
,
470 bmapPtr
->header
.x1
- canvasPtr
->drawableXOrigin
,
471 bmapPtr
->header
.y1
- canvasPtr
->drawableYOrigin
, 1);
477 *--------------------------------------------------------------
481 * Computes the distance from a given point to a given
482 * rectangle, in canvas units.
485 * The return value is 0 if the point whose x and y coordinates
486 * are coordPtr[0] and coordPtr[1] is inside the bitmap. If the
487 * point isn't inside the bitmap then the return value is the
488 * distance from the point to the bitmap.
493 *--------------------------------------------------------------
499 Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
500 Tk_Item
*itemPtr
, /* Item to check against point. */
501 double *coordPtr
/* Pointer to x and y coordinates. */
504 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
505 double x1
, x2
, y1
, y2
, xDiff
, yDiff
;
507 x1
= bmapPtr
->header
.x1
;
508 y1
= bmapPtr
->header
.y1
;
509 x2
= bmapPtr
->header
.x2
;
510 y2
= bmapPtr
->header
.y2
;
513 * Point is outside rectangle.
516 if (coordPtr
[0] < x1
) {
517 xDiff
= x1
- coordPtr
[0];
518 } else if (coordPtr
[0] > x2
) {
519 xDiff
= coordPtr
[0] - x2
;
524 if (coordPtr
[1] < y1
) {
525 yDiff
= y1
- coordPtr
[1];
526 } else if (coordPtr
[1] > y2
) {
527 yDiff
= coordPtr
[1] - y2
;
532 return hypot(xDiff
, yDiff
);
536 *--------------------------------------------------------------
540 * This procedure is called to determine whether an item
541 * lies entirely inside, entirely outside, or overlapping
545 * -1 is returned if the item is entirely outside the area
546 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
547 * inside the given area.
552 *--------------------------------------------------------------
558 Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
559 Tk_Item
*itemPtr
, /* Item to check against rectangle. */
560 double *rectPtr
/* Pointer to array of four coordinates
561 * (x1, y1, x2, y2) describing rectangular
565 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
567 if ((rectPtr
[2] <= bmapPtr
->header
.x1
)
568 || (rectPtr
[0] >= bmapPtr
->header
.x2
)
569 || (rectPtr
[3] <= bmapPtr
->header
.y1
)
570 || (rectPtr
[1] >= bmapPtr
->header
.y2
)) {
573 if ((rectPtr
[0] <= bmapPtr
->header
.x1
)
574 && (rectPtr
[1] <= bmapPtr
->header
.y1
)
575 && (rectPtr
[2] >= bmapPtr
->header
.x2
)
576 && (rectPtr
[3] >= bmapPtr
->header
.y2
)) {
583 *--------------------------------------------------------------
587 * This procedure is invoked to rescale a rectangle or oval
594 * The rectangle or oval referred to by itemPtr is rescaled
595 * so that the following transformation is applied to all
597 * x' = originX + scaleX*(x-originX)
598 * y' = originY + scaleY*(y-originY)
600 *--------------------------------------------------------------
605 Tk_Canvas
*canvasPtr
, /* Canvas containing rectangle. */
606 Tk_Item
*itemPtr
, /* Rectangle to be scaled. */
608 double originY
, /* Origin about which to scale rect. */
609 double scaleX
, /* Amount to scale in X direction. */
610 double scaleY
/* Amount to scale in Y direction. */
613 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
615 bmapPtr
->x
= originX
+ scaleX
*(bmapPtr
->x
- originX
);
616 bmapPtr
->y
= originY
+ scaleY
*(bmapPtr
->y
- originY
);
617 ComputeBitmapBbox(canvasPtr
, bmapPtr
);
621 *--------------------------------------------------------------
625 * This procedure is called to move a rectangle or oval by a
632 * The position of the rectangle or oval is offset by
633 * (xDelta, yDelta), and the bounding box is updated in the
634 * generic part of the item structure.
636 *--------------------------------------------------------------
641 Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
642 Tk_Item
*itemPtr
, /* Item that is being moved. */
644 double deltaY
/* Amount by which item is to be
648 register BitmapItem
*bmapPtr
= (BitmapItem
*) itemPtr
;
650 bmapPtr
->x
+= deltaX
;
651 bmapPtr
->y
+= deltaY
;
652 ComputeBitmapBbox(canvasPtr
, bmapPtr
);