|
|
1.1 root 1: /*
2: * tkCanvBmap.c --
3: *
4: * This file implements bitmap items for canvas widgets.
5: *
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.
14: */
15:
16: #ifndef lint
17: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkCanvBmap.c,v 1.4 92/08/24 09:24:11 ouster Exp $ SPRITE (Berkeley)";
18: #endif
19:
20: #include <stdio.h>
21: #include <math.h>
22: #include "tkint.h"
23: #include "tkcanvas.h"
24:
25: /*
26: * The structure below defines the record for each rectangle/oval item.
27: */
28:
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
33: * bitmap. */
34: Tk_Anchor anchor; /* Where to anchor bitmap relative to
35: * (x,y). */
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. */
41: } BitmapItem;
42:
43: /*
44: * Information used for parsing configuration specs:
45: */
46:
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},
52: #if defined(USE_XPM3)
53: {TK_CONFIG_PIXMAP, "-bitmap", (char *) NULL, (char *) NULL,
54: (char *) NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK},
55: #else
56: {TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
57: (char *) NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK},
58: #endif
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,
64: (char *) NULL, 0, 0}
65: };
66:
67: /*
68: * Prototypes for procedures defined in this file:
69: */
70:
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));
92:
93: /*
94: * The structures below defines the rectangle and oval item types
95: * by means of procedures that can be invoked by generic item code.
96: */
97:
98: Tk_ItemType TkBitmapType = {
99: "bitmap", /* name */
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 */
119: };
120:
121: /*
122: *--------------------------------------------------------------
123: *
124: * CreateBitmap --
125: *
126: * This procedure is invoked to create a new bitmap
127: * item in a canvas.
128: *
129: * Results:
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
134: * caller.
135: *
136: * Side effects:
137: * A new bitmap item is created.
138: *
139: *--------------------------------------------------------------
140: */
141:
142: static int
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. */
149: {
150: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
151:
152: if (argc < 2) {
153: Tcl_AppendResult(canvasPtr->interp, "wrong # args: should be \"",
154: Tk_PathName(canvasPtr->tkwin), "\" create ",
155: itemPtr->typePtr->name, " x y ?options?",
156: (char *) NULL);
157: return TCL_ERROR;
158: }
159:
160: /*
161: * Initialize item's record.
162: */
163:
164: bmapPtr->anchor = TK_ANCHOR_CENTER;
165: bmapPtr->bitmap = None;
166: bmapPtr->fgColor = NULL;
167: bmapPtr->bgColor = NULL;
168: bmapPtr->gc = None;
169:
170: /*
171: * Process the arguments to fill in the item record.
172: */
173:
174: if ((TkGetCanvasCoord(canvasPtr, argv[0], &bmapPtr->x) != TCL_OK)
175: || (TkGetCanvasCoord(canvasPtr, argv[1],
176: &bmapPtr->y) != TCL_OK)) {
177: return TCL_ERROR;
178: }
179:
180: if (ConfigureBitmap(canvasPtr, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
181: DeleteBitmap(itemPtr);
182: return TCL_ERROR;
183: }
184: return TCL_OK;
185: }
186:
187: /*
188: *--------------------------------------------------------------
189: *
190: * BitmapCoords --
191: *
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.
195: *
196: * Results:
197: * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
198: *
199: * Side effects:
200: * The coordinates for the given item may be changed.
201: *
202: *--------------------------------------------------------------
203: */
204:
205: static int
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
211: * argv. */
212: char **argv; /* Array of coordinates: x1, y1,
213: * x2, y2, ... */
214: {
215: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
216:
217: if (argc == 0) {
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)) {
223: return TCL_ERROR;
224: }
225: ComputeBitmapBbox(canvasPtr, bmapPtr);
226: } else {
227: sprintf(canvasPtr->interp->result,
228: "wrong # coordinates: expected 0 or 2, got %d",
229: argc);
230: return TCL_ERROR;
231: }
232: return TCL_OK;
233: }
234:
235: /*
236: *--------------------------------------------------------------
237: *
238: * ConfigureBitmap --
239: *
240: * This procedure is invoked to configure various aspects
241: * of a bitmap item, such as its anchor position.
242: *
243: * Results:
244: * A standard Tcl result code. If an error occurs, then
245: * an error message is left in canvasPtr->interp->result.
246: *
247: * Side effects:
248: * Configuration information may be set for itemPtr.
249: *
250: *--------------------------------------------------------------
251: */
252:
253: static int
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. */
260: {
261: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
262: XGCValues gcValues;
263: GC newGC;
264:
265: if (Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin,
266: configSpecs, argc, argv, (char *) bmapPtr, flags) != TCL_OK) {
267: return TCL_ERROR;
268: }
269:
270: /*
271: * A few of the options require additional processing, such as those
272: * that determine the graphics context.
273: */
274:
275: gcValues.foreground = bmapPtr->fgColor->pixel;
276: if (bmapPtr->bgColor != NULL) {
277: gcValues.background = bmapPtr->bgColor->pixel;
278: } else {
279: gcValues.background = canvasPtr->bgColor->pixel;
280: }
281: newGC = Tk_GetGC(canvasPtr->tkwin, GCForeground|GCBackground, &gcValues);
282: if (bmapPtr->gc != None) {
283: Tk_FreeGC(bmapPtr->gc);
284: }
285: bmapPtr->gc = newGC;
286:
287: ComputeBitmapBbox(canvasPtr, bmapPtr);
288:
289: return TCL_OK;
290: }
291:
292: /*
293: *--------------------------------------------------------------
294: *
295: * DeleteBitmap --
296: *
297: * This procedure is called to clean up the data structure
298: * associated with a bitmap item.
299: *
300: * Results:
301: * None.
302: *
303: * Side effects:
304: * Resources associated with itemPtr are released.
305: *
306: *--------------------------------------------------------------
307: */
308:
309: static void
310: DeleteBitmap(itemPtr)
311: Tk_Item *itemPtr; /* Item that is being deleted. */
312: {
313: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
314:
315: if (bmapPtr->bitmap != None) {
316: #if defined(USE_XPM3)
317: Tk_FreePixmap(bmapPtr->bitmap);
318: #else
319: Tk_FreeBitmap(bmapPtr->bitmap);
320: #endif
321: }
322: if (bmapPtr->fgColor != NULL) {
323: Tk_FreeColor(bmapPtr->fgColor);
324: }
325: if (bmapPtr->bgColor != NULL) {
326: Tk_FreeColor(bmapPtr->bgColor);
327: }
328: if (bmapPtr->gc != NULL) {
329: Tk_FreeGC(bmapPtr->gc);
330: }
331: }
332:
333: /*
334: *--------------------------------------------------------------
335: *
336: * ComputeBitmapBbox --
337: *
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
341: * computed.
342: *
343: * Results:
344: * None.
345: *
346: * Side effects:
347: * The fields x1, y1, x2, and y2 are updated in the header
348: * for itemPtr.
349: *
350: *--------------------------------------------------------------
351: */
352:
353: /* ARGSUSED */
354: static void
355: ComputeBitmapBbox(canvasPtr, bmapPtr)
356: Tk_Canvas *canvasPtr; /* Canvas that contains item. */
357: register BitmapItem *bmapPtr; /* Item whose bbox is to be
358: * recomputed. */
359: {
360: unsigned int width, height;
361: int x, y;
362:
363: x = bmapPtr->x + 0.5;
364: y = bmapPtr->y + 0.5;
365:
366: if (bmapPtr->bitmap == None) {
367: bmapPtr->header.x1 = bmapPtr->header.x2 = x;
368: bmapPtr->header.y1 = bmapPtr->header.y2 = y;
369: return;
370: }
371:
372: /*
373: * Compute location and size of bitmap, using anchor information.
374: */
375:
376: #if defined(USE_XPM3)
377: Tk_SizeOfPixmap(bmapPtr->bitmap, &width, &height);
378: #else
379: Tk_SizeOfBitmap(bmapPtr->bitmap, &width, &height);
380: #endif
381: switch (bmapPtr->anchor) {
382: case TK_ANCHOR_N:
383: x -= width/2;
384: break;
385: case TK_ANCHOR_NE:
386: x -= width;
387: break;
388: case TK_ANCHOR_E:
389: x -= width;
390: y -= height/2;
391: break;
392: case TK_ANCHOR_SE:
393: x -= width;
394: y -= height;
395: break;
396: case TK_ANCHOR_S:
397: x -= width/2;
398: y -= height;
399: break;
400: case TK_ANCHOR_SW:
401: y -= height;
402: break;
403: case TK_ANCHOR_W:
404: y -= height/2;
405: break;
406: case TK_ANCHOR_NW:
407: break;
408: case TK_ANCHOR_CENTER:
409: x -= width/2;
410: y -= height/2;
411: break;
412: }
413:
414: /*
415: * Store the information in the item header.
416: */
417:
418: bmapPtr->header.x1 = x;
419: bmapPtr->header.y1 = y;
420: bmapPtr->header.x2 = x + width;
421: bmapPtr->header.y2 = y + height;
422: }
423:
424: /*
425: *--------------------------------------------------------------
426: *
427: * DisplayBitmap --
428: *
429: * This procedure is invoked to draw a bitmap item in a given
430: * drawable.
431: *
432: * Results:
433: * None.
434: *
435: * Side effects:
436: * ItemPtr is drawn in drawable using the transformation
437: * information in canvasPtr.
438: *
439: *--------------------------------------------------------------
440: */
441:
442: static void
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
447: * item. */
448: {
449: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
450:
451: if (bmapPtr->bitmap != None) {
452: #if defined(USE_XPM3)
453: XCopyArea(Tk_Display(canvasPtr->tkwin), bmapPtr->bitmap, drawable,
454: bmapPtr->gc, 0, 0,
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);
459: #else
460: XCopyPlane(Tk_Display(canvasPtr->tkwin), bmapPtr->bitmap, drawable,
461: bmapPtr->gc, 0, 0,
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);
466: #endif
467: }
468: }
469:
470: /*
471: *--------------------------------------------------------------
472: *
473: * BitmapToPoint --
474: *
475: * Computes the distance from a given point to a given
476: * rectangle, in canvas units.
477: *
478: * Results:
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.
483: *
484: * Side effects:
485: * None.
486: *
487: *--------------------------------------------------------------
488: */
489:
490: /* ARGSUSED */
491: static double
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. */
496: {
497: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
498: double x1, x2, y1, y2, xDiff, yDiff;
499:
500: x1 = bmapPtr->header.x1;
501: y1 = bmapPtr->header.y1;
502: x2 = bmapPtr->header.x2;
503: y2 = bmapPtr->header.y2;
504:
505: /*
506: * Point is outside rectangle.
507: */
508:
509: if (coordPtr[0] < x1) {
510: xDiff = x1 - coordPtr[0];
511: } else if (coordPtr[0] > x2) {
512: xDiff = coordPtr[0] - x2;
513: } else {
514: xDiff = 0;
515: }
516:
517: if (coordPtr[1] < y1) {
518: yDiff = y1 - coordPtr[1];
519: } else if (coordPtr[1] > y2) {
520: yDiff = coordPtr[1] - y2;
521: } else {
522: yDiff = 0;
523: }
524:
525: return hypot(xDiff, yDiff);
526: }
527:
528: /*
529: *--------------------------------------------------------------
530: *
531: * BitmapToArea --
532: *
533: * This procedure is called to determine whether an item
534: * lies entirely inside, entirely outside, or overlapping
535: * a given rectangle.
536: *
537: * Results:
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.
541: *
542: * Side effects:
543: * None.
544: *
545: *--------------------------------------------------------------
546: */
547:
548: /* ARGSUSED */
549: static int
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
555: * area. */
556: {
557: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
558:
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)) {
563: return -1;
564: }
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)) {
569: return 1;
570: }
571: return 0;
572: }
573:
574: /*
575: *--------------------------------------------------------------
576: *
577: * ScaleBitmap --
578: *
579: * This procedure is invoked to rescale a rectangle or oval
580: * item.
581: *
582: * Results:
583: * None.
584: *
585: * Side effects:
586: * The rectangle or oval referred to by itemPtr is rescaled
587: * so that the following transformation is applied to all
588: * point coordinates:
589: * x' = originX + scaleX*(x-originX)
590: * y' = originY + scaleY*(y-originY)
591: *
592: *--------------------------------------------------------------
593: */
594:
595: static void
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. */
602: {
603: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
604:
605: bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);
606: bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);
607: ComputeBitmapBbox(canvasPtr, bmapPtr);
608: }
609:
610: /*
611: *--------------------------------------------------------------
612: *
613: * TranslateBitmap --
614: *
615: * This procedure is called to move a rectangle or oval by a
616: * given amount.
617: *
618: * Results:
619: * None.
620: *
621: * Side effects:
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.
625: *
626: *--------------------------------------------------------------
627: */
628:
629: static void
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
634: * moved. */
635: {
636: register BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
637:
638: bmapPtr->x += deltaX;
639: bmapPtr->y += deltaY;
640: ComputeBitmapBbox(canvasPtr, bmapPtr);
641: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.