OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / generic / tkCanvBmap.c
1 /*
2  * tkCanvBmap.c --
3  *
4  *      This file implements bitmap items for canvas widgets.
5  *
6  * Copyright (c) 1992-1994 The Regents of the University of California.
7  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
8  *
9  * See the file "license.terms" for information on usage and redistribution of
10  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  */
12
13 #include "tkInt.h"
14 #include "tkCanvas.h"
15 #include "default.h"
16
17 /*
18  * The structure below defines the record for each bitmap item.
19  */
20
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
25                                  * bitmap. */
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
37                                  * on screen. */
38 } BitmapItem;
39
40 /*
41  * Information used for parsing configuration specs:
42  */
43
44 static const Tk_CustomOption stateOption = {
45     TkStateParseProc, TkStatePrintProc, INT2PTR(2)
46 };
47 static const Tk_CustomOption tagsOption = {
48     Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
49 };
50
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,
77         &stateOption},
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}
81 };
82
83 /*
84  * Prototypes for functions defined in this file:
85  */
86
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,
97                             BitmapItem *bmapPtr);
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);
114
115 /*
116  * The structures below defines the bitmap item type in terms of functions
117  * that can be invoked by generic item code.
118  */
119
120 Tk_ItemType tkBitmapType = {
121     "bitmap",                   /* name */
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 */
140     NULL,                       /* nextPtr */
141     NULL, 0, NULL, NULL
142 };
143 \f
144 /*
145  *--------------------------------------------------------------
146  *
147  * TkcCreateBitmap --
148  *
149  *      This function is invoked to create a new bitmap item in a canvas.
150  *
151  * Results:
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
155  *      caller.
156  *
157  * Side effects:
158  *      A new bitmap item is created.
159  *
160  *--------------------------------------------------------------
161  */
162
163 static int
164 TkcCreateBitmap(
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. */
171 {
172     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
173     int i;
174
175     if (objc == 0) {
176         Tcl_Panic("canvas did not pass any coords");
177     }
178
179     /*
180      * Initialize item's record.
181      */
182
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;
193     bmapPtr->gc = NULL;
194
195     /*
196      * Process the arguments to fill in the item record. Only 1 (list) or 2 (x
197      * y) coords are allowed.
198      */
199
200     if (objc == 1) {
201         i = 1;
202     } else {
203         const char *arg = Tcl_GetString(objv[1]);
204         i = 2;
205         if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
206             i = 1;
207         }
208     }
209     if (BitmapCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
210         goto error;
211     }
212     if (ConfigureBitmap(interp, canvas, itemPtr, objc-i, objv+i, 0)
213             == TCL_OK) {
214         return TCL_OK;
215     }
216
217   error:
218     DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
219     return TCL_ERROR;
220 }
221 \f
222 /*
223  *--------------------------------------------------------------
224  *
225  * BitmapCoords --
226  *
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.
229  *
230  * Results:
231  *      Returns TCL_OK or TCL_ERROR, and sets the interp's result.
232  *
233  * Side effects:
234  *      The coordinates for the given item may be changed.
235  *
236  *--------------------------------------------------------------
237  */
238
239 static int
240 BitmapCoords(
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
244                                  * modified. */
245     int objc,                   /* Number of coordinates supplied in objv. */
246     Tcl_Obj *const objv[])      /* Array of coordinates: x1, y1, x2, y2, ... */
247 {
248     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
249
250     if (objc == 0) {
251         Tcl_Obj *obj = Tcl_NewObj();
252
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) {
257         if (objc == 1) {
258             if (Tcl_ListObjGetElements(interp, objv[0], &objc,
259                     (Tcl_Obj ***) &objv) != TCL_OK) {
260                 return TCL_ERROR;
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",
265                         NULL);
266                 return TCL_ERROR;
267             }
268         }
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)) {
273             return TCL_ERROR;
274         }
275         ComputeBitmapBbox(canvas, bmapPtr);
276     } else {
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);
280         return TCL_ERROR;
281     }
282     return TCL_OK;
283 }
284 \f
285 /*
286  *--------------------------------------------------------------
287  *
288  * ConfigureBitmap --
289  *
290  *      This function is invoked to configure various aspects of a bitmap
291  *      item, such as its anchor position.
292  *
293  * Results:
294  *      A standard Tcl result code. If an error occurs, then an error message
295  *      is left in the interp's result.
296  *
297  * Side effects:
298  *      Configuration information may be set for itemPtr.
299  *
300  *--------------------------------------------------------------
301  */
302
303 static int
304 ConfigureBitmap(
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. */
311 {
312     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
313     XGCValues gcValues;
314     GC newGC;
315     Tk_Window tkwin;
316     unsigned long mask;
317     XColor *fgColor;
318     XColor *bgColor;
319     Pixmap bitmap;
320     Tk_State state;
321
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)) {
325         return TCL_ERROR;
326     }
327
328     /*
329      * A few of the options require additional processing, such as those that
330      * determine the graphics context.
331      */
332
333     state = itemPtr->state;
334
335     if (bmapPtr->activeFgColor!=NULL ||
336             bmapPtr->activeBgColor!=NULL ||
337             bmapPtr->activeBitmap!=None) {
338         itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
339     } else {
340         itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
341     }
342
343     if (state == TK_STATE_NULL) {
344         state = Canvas(canvas)->canvas_state;
345     }
346     if (state == TK_STATE_HIDDEN) {
347         ComputeBitmapBbox(canvas, bmapPtr);
348         return TCL_OK;
349     }
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;
356         }
357         if (bmapPtr->activeBgColor!=NULL) {
358             bgColor = bmapPtr->activeBgColor;
359         }
360         if (bmapPtr->activeBitmap!=None) {
361             bitmap = bmapPtr->activeBitmap;
362         }
363     } else if (state == TK_STATE_DISABLED) {
364         if (bmapPtr->disabledFgColor!=NULL) {
365             fgColor = bmapPtr->disabledFgColor;
366         }
367         if (bmapPtr->disabledBgColor!=NULL) {
368             bgColor = bmapPtr->disabledBgColor;
369         }
370         if (bmapPtr->disabledBitmap!=None) {
371             bitmap = bmapPtr->disabledBitmap;
372         }
373     }
374
375     if (bitmap == None) {
376         newGC = NULL;
377     } else {
378         gcValues.foreground = fgColor->pixel;
379         mask = GCForeground;
380         if (bgColor != NULL) {
381             gcValues.background = bgColor->pixel;
382             mask |= GCBackground;
383         } else {
384             gcValues.clip_mask = bitmap;
385             mask |= GCClipMask;
386         }
387         newGC = Tk_GetGC(tkwin, mask, &gcValues);
388     }
389     if (bmapPtr->gc != NULL) {
390         Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
391     }
392     bmapPtr->gc = newGC;
393
394     ComputeBitmapBbox(canvas, bmapPtr);
395     return TCL_OK;
396 }
397 \f
398 /*
399  *--------------------------------------------------------------
400  *
401  * DeleteBitmap --
402  *
403  *      This function is called to clean up the data structure associated with
404  *      a bitmap item.
405  *
406  * Results:
407  *      None.
408  *
409  * Side effects:
410  *      Resources associated with itemPtr are released.
411  *
412  *--------------------------------------------------------------
413  */
414
415 static void
416 DeleteBitmap(
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. */
420 {
421     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
422
423     if (bmapPtr->bitmap != None) {
424         Tk_FreeBitmap(display, bmapPtr->bitmap);
425     }
426     if (bmapPtr->activeBitmap != None) {
427         Tk_FreeBitmap(display, bmapPtr->activeBitmap);
428     }
429     if (bmapPtr->disabledBitmap != None) {
430         Tk_FreeBitmap(display, bmapPtr->disabledBitmap);
431     }
432     if (bmapPtr->fgColor != NULL) {
433         Tk_FreeColor(bmapPtr->fgColor);
434     }
435     if (bmapPtr->activeFgColor != NULL) {
436         Tk_FreeColor(bmapPtr->activeFgColor);
437     }
438     if (bmapPtr->disabledFgColor != NULL) {
439         Tk_FreeColor(bmapPtr->disabledFgColor);
440     }
441     if (bmapPtr->bgColor != NULL) {
442         Tk_FreeColor(bmapPtr->bgColor);
443     }
444     if (bmapPtr->activeBgColor != NULL) {
445         Tk_FreeColor(bmapPtr->activeBgColor);
446     }
447     if (bmapPtr->disabledBgColor != NULL) {
448         Tk_FreeColor(bmapPtr->disabledBgColor);
449     }
450     if (bmapPtr->gc != NULL) {
451         Tk_FreeGC(display, bmapPtr->gc);
452     }
453 }
454 \f
455 /*
456  *--------------------------------------------------------------
457  *
458  * ComputeBitmapBbox --
459  *
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.
463  *
464  * Results:
465  *      None.
466  *
467  * Side effects:
468  *      The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
469  *
470  *--------------------------------------------------------------
471  */
472
473         /* ARGSUSED */
474 static void
475 ComputeBitmapBbox(
476     Tk_Canvas canvas,           /* Canvas that contains item. */
477     BitmapItem *bmapPtr)        /* Item whose bbox is to be recomputed. */
478 {
479     int width, height;
480     int x, y;
481     Pixmap bitmap;
482     Tk_State state = bmapPtr->header.state;
483
484     if (state == TK_STATE_NULL) {
485         state = Canvas(canvas)->canvas_state;
486     }
487     bitmap = bmapPtr->bitmap;
488     if (Canvas(canvas)->currentItemPtr == (Tk_Item *)bmapPtr) {
489         if (bmapPtr->activeBitmap!=None) {
490             bitmap = bmapPtr->activeBitmap;
491         }
492     } else if (state==TK_STATE_DISABLED) {
493         if (bmapPtr->disabledBitmap!=None) {
494             bitmap = bmapPtr->disabledBitmap;
495         }
496     }
497
498     x = (int) (bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5));
499     y = (int) (bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5));
500
501     if (state==TK_STATE_HIDDEN || bitmap == None) {
502         bmapPtr->header.x1 = bmapPtr->header.x2 = x;
503         bmapPtr->header.y1 = bmapPtr->header.y2 = y;
504         return;
505     }
506
507     /*
508      * Compute location and size of bitmap, using anchor information.
509      */
510
511     Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,
512             &width, &height);
513     switch (bmapPtr->anchor) {
514     case TK_ANCHOR_N:
515         x -= width/2;
516         break;
517     case TK_ANCHOR_NE:
518         x -= width;
519         break;
520     case TK_ANCHOR_E:
521         x -= width;
522         y -= height/2;
523         break;
524     case TK_ANCHOR_SE:
525         x -= width;
526         y -= height;
527         break;
528     case TK_ANCHOR_S:
529         x -= width/2;
530         y -= height;
531         break;
532     case TK_ANCHOR_SW:
533         y -= height;
534         break;
535     case TK_ANCHOR_W:
536         y -= height/2;
537         break;
538     case TK_ANCHOR_NW:
539         break;
540     case TK_ANCHOR_CENTER:
541         x -= width/2;
542         y -= height/2;
543         break;
544     }
545
546     /*
547      * Store the information in the item header.
548      */
549
550     bmapPtr->header.x1 = x;
551     bmapPtr->header.y1 = y;
552     bmapPtr->header.x2 = x + width;
553     bmapPtr->header.y2 = y + height;
554 }
555 \f
556 /*
557  *--------------------------------------------------------------
558  *
559  * DisplayBitmap --
560  *
561  *      This function is invoked to draw a bitmap item in a given drawable.
562  *
563  * Results:
564  *      None.
565  *
566  * Side effects:
567  *      ItemPtr is drawn in drawable using the transformation information in
568  *      canvas.
569  *
570  *--------------------------------------------------------------
571  */
572
573 static void
574 DisplayBitmap(
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). */
582 {
583     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
584     int bmapX, bmapY, bmapWidth, bmapHeight;
585     short drawableX, drawableY;
586     Pixmap bitmap;
587     Tk_State state = itemPtr->state;
588
589     /*
590      * If the area being displayed doesn't cover the whole bitmap, then only
591      * redisplay the part of the bitmap that needs redisplay.
592      */
593
594     if (state == TK_STATE_NULL) {
595         state = Canvas(canvas)->canvas_state;
596     }
597     bitmap = bmapPtr->bitmap;
598     if (Canvas(canvas)->currentItemPtr == itemPtr) {
599         if (bmapPtr->activeBitmap!=None) {
600             bitmap = bmapPtr->activeBitmap;
601         }
602     } else if (state == TK_STATE_DISABLED) {
603         if (bmapPtr->disabledBitmap!=None) {
604             bitmap = bmapPtr->disabledBitmap;
605         }
606     }
607
608     if (bitmap != None) {
609         if (x > bmapPtr->header.x1) {
610             bmapX = x - bmapPtr->header.x1;
611             bmapWidth = bmapPtr->header.x2 - x;
612         } else {
613             bmapX = 0;
614             if ((x+width) < bmapPtr->header.x2) {
615                 bmapWidth = x + width - bmapPtr->header.x1;
616             } else {
617                 bmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1;
618             }
619         }
620         if (y > bmapPtr->header.y1) {
621             bmapY = y - bmapPtr->header.y1;
622             bmapHeight = bmapPtr->header.y2 - y;
623         } else {
624             bmapY = 0;
625             if ((y+height) < bmapPtr->header.y2) {
626                 bmapHeight = y + height - bmapPtr->header.y1;
627             } else {
628                 bmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1;
629             }
630         }
631         Tk_CanvasDrawableCoords(canvas,
632                 (double) (bmapPtr->header.x1 + bmapX),
633                 (double) (bmapPtr->header.y1 + bmapY),
634                 &drawableX, &drawableY);
635
636         /*
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).
640          */
641
642         XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,
643                 drawableY - bmapY);
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);
648     }
649 }
650 \f
651 /*
652  *--------------------------------------------------------------
653  *
654  * BitmapToPoint --
655  *
656  *      Computes the distance from a given point to a given rectangle, in
657  *      canvas units.
658  *
659  * Results:
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
663  *      to the bitmap.
664  *
665  * Side effects:
666  *      None.
667  *
668  *--------------------------------------------------------------
669  */
670
671         /* ARGSUSED */
672 static double
673 BitmapToPoint(
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. */
677 {
678     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
679     double x1, x2, y1, y2, xDiff, yDiff;
680
681     x1 = bmapPtr->header.x1;
682     y1 = bmapPtr->header.y1;
683     x2 = bmapPtr->header.x2;
684     y2 = bmapPtr->header.y2;
685
686     /*
687      * Point is outside rectangle.
688      */
689
690     if (coordPtr[0] < x1) {
691         xDiff = x1 - coordPtr[0];
692     } else if (coordPtr[0] > x2)  {
693         xDiff = coordPtr[0] - x2;
694     } else {
695         xDiff = 0;
696     }
697
698     if (coordPtr[1] < y1) {
699         yDiff = y1 - coordPtr[1];
700     } else if (coordPtr[1] > y2)  {
701         yDiff = coordPtr[1] - y2;
702     } else {
703         yDiff = 0;
704     }
705
706     return hypot(xDiff, yDiff);
707 }
708 \f
709 /*
710  *--------------------------------------------------------------
711  *
712  * BitmapToArea --
713  *
714  *      This function is called to determine whether an item lies entirely
715  *      inside, entirely outside, or overlapping a given rectangle.
716  *
717  * Results:
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
720  *      area.
721  *
722  * Side effects:
723  *      None.
724  *
725  *--------------------------------------------------------------
726  */
727
728         /* ARGSUSED */
729 static int
730 BitmapToArea(
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
735                                  * area. */
736 {
737     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
738
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)) {
743         return -1;
744     }
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)) {
749         return 1;
750     }
751     return 0;
752 }
753 \f
754 /*
755  *--------------------------------------------------------------
756  *
757  * ScaleBitmap --
758  *
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.
762  *
763  * Results:
764  *      None.
765  *
766  * Side effects:
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)
771  *
772  *--------------------------------------------------------------
773  */
774
775 static void
776 ScaleBitmap(
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. */
783 {
784     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
785
786     bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);
787     bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);
788     ComputeBitmapBbox(canvas, bmapPtr);
789 }
790 \f
791 /*
792  *--------------------------------------------------------------
793  *
794  * TranslateBitmap --
795  *
796  *      This function is called to move an item by a given amount.
797  *
798  * Results:
799  *      None.
800  *
801  * Side effects:
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.
804  *
805  *--------------------------------------------------------------
806  */
807
808 static void
809 TranslateBitmap(
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. */
814 {
815     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
816
817     bmapPtr->x += deltaX;
818     bmapPtr->y += deltaY;
819     ComputeBitmapBbox(canvas, bmapPtr);
820 }
821 \f
822 /*
823  *--------------------------------------------------------------
824  *
825  * BitmapToPostscript --
826  *
827  *      This function is called to generate Postscript for bitmap items.
828  *
829  * Results:
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.
834  *
835  * Side effects:
836  *      None.
837  *
838  *--------------------------------------------------------------
839  */
840
841 static int
842 BitmapToPostscript(
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
848                                  * being created. */
849 {
850     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
851     double x, y;
852     int width, height, rowsAtOnce, rowsThisTime;
853     int curRow;
854     XColor *fgColor;
855     XColor *bgColor;
856     Pixmap bitmap;
857     Tk_State state = itemPtr->state;
858     Tcl_Obj *psObj;
859     Tcl_InterpState interpState;
860
861     if (state == TK_STATE_NULL) {
862         state = Canvas(canvas)->canvas_state;
863     }
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;
870         }
871         if (bmapPtr->activeBgColor!=NULL) {
872             bgColor = bmapPtr->activeBgColor;
873         }
874         if (bmapPtr->activeBitmap!=None) {
875             bitmap = bmapPtr->activeBitmap;
876         }
877     } else if (state == TK_STATE_DISABLED) {
878         if (bmapPtr->disabledFgColor!=NULL) {
879             fgColor = bmapPtr->disabledFgColor;
880         }
881         if (bmapPtr->disabledBgColor!=NULL) {
882             bgColor = bmapPtr->disabledBgColor;
883         }
884         if (bmapPtr->disabledBitmap!=None) {
885             bitmap = bmapPtr->disabledBitmap;
886         }
887     }
888
889     if (bitmap == None) {
890         return TCL_OK;
891     }
892
893     /*
894      * Compute the coordinates of the lower-left corner of the bitmap, taking
895      * into account the anchor position for the bitmp.
896      */
897
898     x = bmapPtr->x;
899     y = Tk_CanvasPsY(canvas, bmapPtr->y);
900     Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,
901             &width, &height);
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;
912     }
913
914     /*
915      * Make our working space.
916      */
917
918     psObj = Tcl_NewObj();
919     interpState = Tcl_SaveInterpState(interp, TCL_OK);
920
921     /*
922      * Color the background, if there is one.
923      */
924
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);
930
931         Tcl_ResetResult(interp);
932         if (Tk_CanvasPsColor(interp, canvas, bgColor) != TCL_OK) {
933             goto error;
934         }
935         Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
936
937         Tcl_AppendToObj(psObj, "fill\n", -1);
938     }
939
940     /*
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.
945      */
946
947     if (fgColor != NULL) {
948         Tcl_ResetResult(interp);
949         if (Tk_CanvasPsColor(interp, canvas, fgColor) != TCL_OK) {
950             goto error;
951         }
952         Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
953
954         if (width > 60000) {
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);
959             goto error;
960         }
961
962         rowsAtOnce = 60000/width;
963         if (rowsAtOnce < 1) {
964             rowsAtOnce = 1;
965         }
966
967         Tcl_AppendPrintfToObj(psObj, "%.15g %.15g translate\n", x, y+height);
968
969         for (curRow = 0; curRow < height; curRow += rowsAtOnce) {
970             rowsThisTime = rowsAtOnce;
971             if (rowsThisTime > (height - curRow)) {
972                 rowsThisTime = height - curRow;
973             }
974
975             Tcl_AppendPrintfToObj(psObj,
976                     "0 -%.15g translate\n%d %d true matrix {\n",
977                     (double) rowsThisTime, width, rowsThisTime);
978
979             Tcl_ResetResult(interp);
980             if (Tk_CanvasPsBitmap(interp, canvas, bitmap,
981                     0, curRow, width, rowsThisTime) != TCL_OK) {
982                 goto error;
983             }
984             Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
985
986             Tcl_AppendToObj(psObj, "\n} imagemask\n", -1);
987         }
988     }
989
990     /*
991      * Plug the accumulated postscript back into the result.
992      */
993
994     (void) Tcl_RestoreInterpState(interp, interpState);
995     Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
996     Tcl_DecrRefCount(psObj);
997     return TCL_OK;
998
999   error:
1000     Tcl_DiscardInterpState(interpState);
1001     Tcl_DecrRefCount(psObj);
1002     return TCL_ERROR;
1003 }
1004 \f
1005 /*
1006  * Local Variables:
1007  * mode: c
1008  * c-basic-offset: 4
1009  * fill-column: 78
1010  * End:
1011  */