tkCanvBmap.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:29k
源码类别:

通讯编程

开发平台:

Visual 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
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: tkCanvBmap.c,v 1.7.2.2 2005/02/11 19:27:52 hobbs Exp $
  13.  */
  14. #include <stdio.h>
  15. #include "tkInt.h"
  16. #include "tkPort.h"
  17. #include "tkCanvas.h"
  18. /*
  19.  * The structure below defines the record for each bitmap item.
  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
  27.  * (x,y). */
  28.     Pixmap bitmap; /* Bitmap to display in window. */
  29.     Pixmap activeBitmap; /* Bitmap to display in window. */
  30.     Pixmap disabledBitmap; /* Bitmap to display in window. */
  31.     XColor *fgColor; /* Foreground color to use for bitmap. */
  32.     XColor *activeFgColor; /* Foreground color to use for bitmap. */
  33.     XColor *disabledFgColor; /* Foreground color to use for bitmap. */
  34.     XColor *bgColor; /* Background color to use for bitmap. */
  35.     XColor *activeBgColor; /* Background color to use for bitmap. */
  36.     XColor *disabledBgColor; /* Background color to use for bitmap. */
  37.     GC gc; /* Graphics context to use for drawing
  38.  * bitmap on screen. */
  39. } BitmapItem;
  40. /*
  41.  * Information used for parsing configuration specs:
  42.  */
  43. static Tk_CustomOption stateOption = {
  44.     (Tk_OptionParseProc *) TkStateParseProc,
  45.     TkStatePrintProc, (ClientData) 2
  46. };
  47. static Tk_CustomOption tagsOption = {
  48.     (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
  49.     Tk_CanvasTagsPrintProc, (ClientData) NULL
  50. };
  51. static Tk_ConfigSpec configSpecs[] = {
  52.     {TK_CONFIG_COLOR, "-activebackground", (char *) NULL, (char *) NULL,
  53. (char *) NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK},
  54.     {TK_CONFIG_BITMAP, "-activebitmap", (char *) NULL, (char *) NULL,
  55. (char *) NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK},
  56.     {TK_CONFIG_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
  57. (char *) NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK},
  58.     {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
  59. "center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
  60.     {TK_CONFIG_COLOR, "-background", (char *) NULL, (char *) NULL,
  61. (char *) NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK},
  62.     {TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
  63. (char *) NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK},
  64.     {TK_CONFIG_COLOR, "-disabledbackground", (char *) NULL, (char *) NULL,
  65. (char *) NULL, Tk_Offset(BitmapItem, disabledBgColor),
  66. TK_CONFIG_NULL_OK},
  67.     {TK_CONFIG_BITMAP, "-disabledbitmap", (char *) NULL, (char *) NULL,
  68. (char *) NULL, Tk_Offset(BitmapItem, disabledBitmap),
  69. TK_CONFIG_NULL_OK},
  70.     {TK_CONFIG_COLOR, "-disabledforeground", (char *) NULL, (char *) NULL,
  71. (char *) NULL, Tk_Offset(BitmapItem, disabledFgColor),
  72. TK_CONFIG_NULL_OK},
  73.     {TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL,
  74. "black", Tk_Offset(BitmapItem, fgColor), 0},
  75.     {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
  76. (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
  77. &stateOption},
  78.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  79. (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
  80.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  81. (char *) NULL, 0, 0}
  82. };
  83. /*
  84.  * Prototypes for procedures defined in this file:
  85.  */
  86. static int BitmapCoords _ANSI_ARGS_((Tcl_Interp *interp,
  87.     Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
  88.     Tcl_Obj *CONST objv[]));
  89. static int BitmapToArea _ANSI_ARGS_((Tk_Canvas canvas,
  90.     Tk_Item *itemPtr, double *rectPtr));
  91. static double BitmapToPoint _ANSI_ARGS_((Tk_Canvas canvas,
  92.     Tk_Item *itemPtr, double *coordPtr));
  93. static int BitmapToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
  94.     Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
  95. static void ComputeBitmapBbox _ANSI_ARGS_((Tk_Canvas canvas,
  96.     BitmapItem *bmapPtr));
  97. static int ConfigureBitmap _ANSI_ARGS_((Tcl_Interp *interp,
  98.     Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
  99.     Tcl_Obj *CONST objv[], int flags));
  100. static int TkcCreateBitmap _ANSI_ARGS_((Tcl_Interp *interp,
  101.     Tk_Canvas canvas, struct Tk_Item *itemPtr,
  102.     int objc, Tcl_Obj *CONST objv[]));
  103. static void DeleteBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  104.     Tk_Item *itemPtr, Display *display));
  105. static void DisplayBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  106.     Tk_Item *itemPtr, Display *display, Drawable dst,
  107.     int x, int y, int width, int height));
  108. static void ScaleBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  109.     Tk_Item *itemPtr, double originX, double originY,
  110.     double scaleX, double scaleY));
  111. static void TranslateBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  112.     Tk_Item *itemPtr, double deltaX, double deltaY));
  113. /*
  114.  * The structures below defines the bitmap item type in terms of
  115.  * procedures that can be invoked by generic item code.
  116.  */
  117. Tk_ItemType tkBitmapType = {
  118.     "bitmap", /* name */
  119.     sizeof(BitmapItem), /* itemSize */
  120.     TkcCreateBitmap, /* createProc */
  121.     configSpecs, /* configSpecs */
  122.     ConfigureBitmap, /* configureProc */
  123.     BitmapCoords, /* coordProc */
  124.     DeleteBitmap, /* deleteProc */
  125.     DisplayBitmap, /* displayProc */
  126.     TK_CONFIG_OBJS, /* flags */
  127.     BitmapToPoint, /* pointProc */
  128.     BitmapToArea, /* areaProc */
  129.     BitmapToPostscript, /* postscriptProc */
  130.     ScaleBitmap, /* scaleProc */
  131.     TranslateBitmap, /* translateProc */
  132.     (Tk_ItemIndexProc *) NULL, /* indexProc */
  133.     (Tk_ItemCursorProc *) NULL, /* icursorProc */
  134.     (Tk_ItemSelectionProc *) NULL, /* selectionProc */
  135.     (Tk_ItemInsertProc *) NULL, /* insertProc */
  136.     (Tk_ItemDCharsProc *) NULL, /* dTextProc */
  137.     (Tk_ItemType *) NULL, /* nextPtr */
  138. };
  139. /*
  140.  *--------------------------------------------------------------
  141.  *
  142.  * TkcCreateBitmap --
  143.  *
  144.  * This procedure is invoked to create a new bitmap
  145.  * item in a canvas.
  146.  *
  147.  * Results:
  148.  * A standard Tcl return value.  If an error occurred in
  149.  * creating the item, then an error message is left in
  150.  * the interp's result;  in this case itemPtr is left uninitialized,
  151.  * so it can be safely freed by the caller.
  152.  *
  153.  * Side effects:
  154.  * A new bitmap item is created.
  155.  *
  156.  *--------------------------------------------------------------
  157.  */
  158. static int
  159. TkcCreateBitmap(interp, canvas, itemPtr, objc, objv)
  160.     Tcl_Interp *interp; /* Interpreter for error reporting. */
  161.     Tk_Canvas canvas; /* Canvas to hold new item. */
  162.     Tk_Item *itemPtr; /* Record to hold new item;  header
  163.  * has been initialized by caller. */
  164.     int objc; /* Number of arguments in objv. */
  165.     Tcl_Obj *CONST objv[]; /* Arguments describing rectangle. */
  166. {
  167.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  168.     int i;
  169.     if (objc == 0) {
  170. Tcl_Panic("canvas did not pass any coordsn");
  171.     }
  172.     /*
  173.      * Initialize item's record.
  174.      */
  175.     bmapPtr->anchor = TK_ANCHOR_CENTER;
  176.     bmapPtr->bitmap = None;
  177.     bmapPtr->activeBitmap = None;
  178.     bmapPtr->disabledBitmap = None;
  179.     bmapPtr->fgColor = NULL;
  180.     bmapPtr->activeFgColor = NULL;
  181.     bmapPtr->disabledFgColor = NULL;
  182.     bmapPtr->bgColor = NULL;
  183.     bmapPtr->activeBgColor = NULL;
  184.     bmapPtr->disabledBgColor = NULL;
  185.     bmapPtr->gc = None;
  186.     /*
  187.      * Process the arguments to fill in the item record.
  188.      * Only 1 (list) or 2 (x y) coords are allowed.
  189.      */
  190.     if (objc == 1) {
  191. i = 1;
  192.     } else {
  193. char *arg = Tcl_GetString(objv[1]);
  194. i = 2;
  195. if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
  196.     i = 1;
  197. }
  198.     }
  199.     if (BitmapCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
  200. goto error;
  201.     }
  202.     if (ConfigureBitmap(interp, canvas, itemPtr, objc-i, objv+i, 0)
  203.     == TCL_OK) {
  204. return TCL_OK;
  205.     }
  206.     error:
  207.     DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
  208.     return TCL_ERROR;
  209. }
  210. /*
  211.  *--------------------------------------------------------------
  212.  *
  213.  * BitmapCoords --
  214.  *
  215.  * This procedure is invoked to process the "coords" widget
  216.  * command on bitmap items.  See the user documentation for
  217.  * details on what it does.
  218.  *
  219.  * Results:
  220.  * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
  221.  *
  222.  * Side effects:
  223.  * The coordinates for the given item may be changed.
  224.  *
  225.  *--------------------------------------------------------------
  226.  */
  227. static int
  228. BitmapCoords(interp, canvas, itemPtr, objc, objv)
  229.     Tcl_Interp *interp; /* Used for error reporting. */
  230.     Tk_Canvas canvas; /* Canvas containing item. */
  231.     Tk_Item *itemPtr; /* Item whose coordinates are to be
  232.  * read or modified. */
  233.     int objc; /* Number of coordinates supplied in
  234.  * objv. */
  235.     Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1,
  236.  * x2, y2, ... */
  237. {
  238.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  239.     if (objc == 0) {
  240. Tcl_Obj *obj = Tcl_NewObj();
  241. Tcl_Obj *subobj = Tcl_NewDoubleObj(bmapPtr->x);
  242. Tcl_ListObjAppendElement(interp, obj, subobj);
  243. subobj = Tcl_NewDoubleObj(bmapPtr->y);
  244. Tcl_ListObjAppendElement(interp, obj, subobj);
  245. Tcl_SetObjResult(interp, obj);
  246.     } else if (objc < 3) {
  247. if (objc == 1) {
  248.     if (Tcl_ListObjGetElements(interp, objv[0], &objc,
  249.     (Tcl_Obj ***) &objv) != TCL_OK) {
  250. return TCL_ERROR;
  251.     } else if (objc != 2) {
  252. char buf[64 + TCL_INTEGER_SPACE];
  253. sprintf(buf, "wrong # coordinates: expected 2, got %d", objc);
  254. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  255. return TCL_ERROR;
  256.     }
  257. }
  258. if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],
  259. &bmapPtr->x) != TCL_OK)
  260. || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
  261. &bmapPtr->y) != TCL_OK)) {
  262.     return TCL_ERROR;
  263. }
  264. ComputeBitmapBbox(canvas, bmapPtr);
  265.     } else {
  266. char buf[64 + TCL_INTEGER_SPACE];
  267. sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", objc);
  268. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  269. return TCL_ERROR;
  270.     }
  271.     return TCL_OK;
  272. }
  273. /*
  274.  *--------------------------------------------------------------
  275.  *
  276.  * ConfigureBitmap --
  277.  *
  278.  * This procedure is invoked to configure various aspects
  279.  * of a bitmap item, such as its anchor position.
  280.  *
  281.  * Results:
  282.  * A standard Tcl result code.  If an error occurs, then
  283.  * an error message is left in the interp's result.
  284.  *
  285.  * Side effects:
  286.  * Configuration information may be set for itemPtr.
  287.  *
  288.  *--------------------------------------------------------------
  289.  */
  290. static int
  291. ConfigureBitmap(interp, canvas, itemPtr, objc, objv, flags)
  292.     Tcl_Interp *interp; /* Used for error reporting. */
  293.     Tk_Canvas canvas; /* Canvas containing itemPtr. */
  294.     Tk_Item *itemPtr; /* Bitmap item to reconfigure. */
  295.     int objc; /* Number of elements in objv.  */
  296.     Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */
  297.     int flags; /* Flags to pass to Tk_ConfigureWidget. */
  298. {
  299.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  300.     XGCValues gcValues;
  301.     GC newGC;
  302.     Tk_Window tkwin;
  303.     unsigned long mask;
  304.     XColor *fgColor;
  305.     XColor *bgColor;
  306.     Pixmap bitmap;
  307.     Tk_State state;
  308.     tkwin = Tk_CanvasTkwin(canvas);
  309.     if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
  310.     (CONST char **) objv, (char *) bmapPtr, flags|TK_CONFIG_OBJS)) {
  311. return TCL_ERROR;
  312.     }
  313.     /*
  314.      * A few of the options require additional processing, such as those
  315.      * that determine the graphics context.
  316.      */
  317.     state = itemPtr->state;
  318.     if (bmapPtr->activeFgColor!=NULL ||
  319.     bmapPtr->activeBgColor!=NULL ||
  320.     bmapPtr->activeBitmap!=None) {
  321. itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
  322.     } else {
  323. itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
  324.     }
  325.     if (state == TK_STATE_NULL) {
  326. state = ((TkCanvas *)canvas)->canvas_state;
  327.     }
  328.     if (state == TK_STATE_HIDDEN) {
  329. ComputeBitmapBbox(canvas, bmapPtr);
  330. return TCL_OK;
  331.     }
  332.     fgColor = bmapPtr->fgColor;
  333.     bgColor = bmapPtr->bgColor;
  334.     bitmap = bmapPtr->bitmap;
  335.     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
  336. if (bmapPtr->activeFgColor!=NULL) {
  337.     fgColor = bmapPtr->activeFgColor;
  338. }
  339. if (bmapPtr->activeBgColor!=NULL) {
  340.     bgColor = bmapPtr->activeBgColor;
  341. }
  342. if (bmapPtr->activeBitmap!=None) {
  343.     bitmap = bmapPtr->activeBitmap;
  344. }
  345.     } else if (state == TK_STATE_DISABLED) {
  346. if (bmapPtr->disabledFgColor!=NULL) {
  347.     fgColor = bmapPtr->disabledFgColor;
  348. }
  349. if (bmapPtr->disabledBgColor!=NULL) {
  350.     bgColor = bmapPtr->disabledBgColor;
  351. }
  352. if (bmapPtr->disabledBitmap!=None) {
  353.     bitmap = bmapPtr->disabledBitmap;
  354. }
  355.     }
  356.     if (bitmap == None) {
  357. newGC = None;
  358.     } else {
  359. gcValues.foreground = fgColor->pixel;
  360. mask = GCForeground;
  361. if (bgColor != NULL) {
  362.     gcValues.background = bgColor->pixel;
  363.     mask |= GCBackground;
  364. } else {
  365.     gcValues.clip_mask = bitmap;
  366.     mask |= GCClipMask;
  367. }
  368. newGC = Tk_GetGC(tkwin, mask, &gcValues);
  369.     }
  370.     if (bmapPtr->gc != None) {
  371. Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
  372.     }
  373.     bmapPtr->gc = newGC;
  374.     ComputeBitmapBbox(canvas, bmapPtr);
  375.     return TCL_OK;
  376. }
  377. /*
  378.  *--------------------------------------------------------------
  379.  *
  380.  * DeleteBitmap --
  381.  *
  382.  * This procedure is called to clean up the data structure
  383.  * associated with a bitmap item.
  384.  *
  385.  * Results:
  386.  * None.
  387.  *
  388.  * Side effects:
  389.  * Resources associated with itemPtr are released.
  390.  *
  391.  *--------------------------------------------------------------
  392.  */
  393. static void
  394. DeleteBitmap(canvas, itemPtr, display)
  395.     Tk_Canvas canvas; /* Info about overall canvas widget. */
  396.     Tk_Item *itemPtr; /* Item that is being deleted. */
  397.     Display *display; /* Display containing window for
  398.  * canvas. */
  399. {
  400.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  401.     if (bmapPtr->bitmap != None) {
  402. Tk_FreeBitmap(display, bmapPtr->bitmap);
  403.     }
  404.     if (bmapPtr->activeBitmap != None) {
  405. Tk_FreeBitmap(display, bmapPtr->activeBitmap);
  406.     }
  407.     if (bmapPtr->disabledBitmap != None) {
  408. Tk_FreeBitmap(display, bmapPtr->disabledBitmap);
  409.     }
  410.     if (bmapPtr->fgColor != NULL) {
  411. Tk_FreeColor(bmapPtr->fgColor);
  412.     }
  413.     if (bmapPtr->activeFgColor != NULL) {
  414. Tk_FreeColor(bmapPtr->activeFgColor);
  415.     }
  416.     if (bmapPtr->disabledFgColor != NULL) {
  417. Tk_FreeColor(bmapPtr->disabledFgColor);
  418.     }
  419.     if (bmapPtr->bgColor != NULL) {
  420. Tk_FreeColor(bmapPtr->bgColor);
  421.     }
  422.     if (bmapPtr->activeBgColor != NULL) {
  423. Tk_FreeColor(bmapPtr->activeBgColor);
  424.     }
  425.     if (bmapPtr->disabledBgColor != NULL) {
  426. Tk_FreeColor(bmapPtr->disabledBgColor);
  427.     }
  428.     if (bmapPtr->gc != NULL) {
  429. Tk_FreeGC(display, bmapPtr->gc);
  430.     }
  431. }
  432. /*
  433.  *--------------------------------------------------------------
  434.  *
  435.  * ComputeBitmapBbox --
  436.  *
  437.  * This procedure is invoked to compute the bounding box of
  438.  * all the pixels that may be drawn as part of a bitmap item.
  439.  * This procedure is where the child bitmap's placement is
  440.  * computed.
  441.  *
  442.  * Results:
  443.  * None.
  444.  *
  445.  * Side effects:
  446.  * The fields x1, y1, x2, and y2 are updated in the header
  447.  * for itemPtr.
  448.  *
  449.  *--------------------------------------------------------------
  450.  */
  451. /* ARGSUSED */
  452. static void
  453. ComputeBitmapBbox(canvas, bmapPtr)
  454.     Tk_Canvas canvas; /* Canvas that contains item. */
  455.     BitmapItem *bmapPtr; /* Item whose bbox is to be
  456.  * recomputed. */
  457. {
  458.     int width, height;
  459.     int x, y;
  460.     Pixmap bitmap;
  461.     Tk_State state = bmapPtr->header.state;
  462.     if (state == TK_STATE_NULL) {
  463. state = ((TkCanvas *)canvas)->canvas_state;
  464.     }
  465.     bitmap = bmapPtr->bitmap;
  466.     if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)bmapPtr) {
  467. if (bmapPtr->activeBitmap!=None) {
  468.     bitmap = bmapPtr->activeBitmap;
  469. }
  470.     } else if (state==TK_STATE_DISABLED) {
  471. if (bmapPtr->disabledBitmap!=None) {
  472.     bitmap = bmapPtr->disabledBitmap;
  473. }
  474.     }
  475.     x = (int) (bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5));
  476.     y = (int) (bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5));
  477.     if (state==TK_STATE_HIDDEN || bitmap == None) {
  478. bmapPtr->header.x1 = bmapPtr->header.x2 = x;
  479. bmapPtr->header.y1 = bmapPtr->header.y2 = y;
  480. return;
  481.     }
  482.     /*
  483.      * Compute location and size of bitmap, using anchor information.
  484.      */
  485.     Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,
  486.     &width, &height);
  487.     switch (bmapPtr->anchor) {
  488. case TK_ANCHOR_N:
  489.     x -= width/2;
  490.     break;
  491. case TK_ANCHOR_NE:
  492.     x -= width;
  493.     break;
  494. case TK_ANCHOR_E:
  495.     x -= width;
  496.     y -= height/2;
  497.     break;
  498. case TK_ANCHOR_SE:
  499.     x -= width;
  500.     y -= height;
  501.     break;
  502. case TK_ANCHOR_S:
  503.     x -= width/2;
  504.     y -= height;
  505.     break;
  506. case TK_ANCHOR_SW:
  507.     y -= height;
  508.     break;
  509. case TK_ANCHOR_W:
  510.     y -= height/2;
  511.     break;
  512. case TK_ANCHOR_NW:
  513.     break;
  514. case TK_ANCHOR_CENTER:
  515.     x -= width/2;
  516.     y -= height/2;
  517.     break;
  518.     }
  519.     /*
  520.      * Store the information in the item header.
  521.      */
  522.     bmapPtr->header.x1 = x;
  523.     bmapPtr->header.y1 = y;
  524.     bmapPtr->header.x2 = x + width;
  525.     bmapPtr->header.y2 = y + height;
  526. }
  527. /*
  528.  *--------------------------------------------------------------
  529.  *
  530.  * DisplayBitmap --
  531.  *
  532.  * This procedure is invoked to draw a bitmap item in a given
  533.  * drawable.
  534.  *
  535.  * Results:
  536.  * None.
  537.  *
  538.  * Side effects:
  539.  * ItemPtr is drawn in drawable using the transformation
  540.  * information in canvas.
  541.  *
  542.  *--------------------------------------------------------------
  543.  */
  544. static void
  545. DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height)
  546.     Tk_Canvas canvas; /* Canvas that contains item. */
  547.     Tk_Item *itemPtr; /* Item to be displayed. */
  548.     Display *display; /* Display on which to draw item. */
  549.     Drawable drawable; /* Pixmap or window in which to draw
  550.  * item. */
  551.     int x, y, width, height; /* Describes region of canvas that
  552.  * must be redisplayed (not used). */
  553. {
  554.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  555.     int bmapX, bmapY, bmapWidth, bmapHeight;
  556.     short drawableX, drawableY;
  557.     Pixmap bitmap;
  558.     Tk_State state = itemPtr->state;
  559.     /*
  560.      * If the area being displayed doesn't cover the whole bitmap,
  561.      * then only redisplay the part of the bitmap that needs
  562.      * redisplay.
  563.      */
  564.     if (state == TK_STATE_NULL) {
  565. state = ((TkCanvas *)canvas)->canvas_state;
  566.     }
  567.     bitmap = bmapPtr->bitmap;
  568.     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
  569. if (bmapPtr->activeBitmap!=None) {
  570.     bitmap = bmapPtr->activeBitmap;
  571. }
  572.     } else if (state == TK_STATE_DISABLED) {
  573. if (bmapPtr->disabledBitmap!=None) {
  574.     bitmap = bmapPtr->disabledBitmap;
  575. }
  576.     }
  577.     if (bitmap != None) {
  578. if (x > bmapPtr->header.x1) {
  579.     bmapX = x - bmapPtr->header.x1;
  580.     bmapWidth = bmapPtr->header.x2 - x;
  581. } else {
  582.     bmapX = 0;
  583.     if ((x+width) < bmapPtr->header.x2) {
  584. bmapWidth = x + width - bmapPtr->header.x1;
  585.     } else {
  586. bmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1;
  587.     }
  588. }
  589. if (y > bmapPtr->header.y1) {
  590.     bmapY = y - bmapPtr->header.y1;
  591.     bmapHeight = bmapPtr->header.y2 - y;
  592. } else {
  593.     bmapY = 0;
  594.     if ((y+height) < bmapPtr->header.y2) {
  595. bmapHeight = y + height - bmapPtr->header.y1;
  596.     } else {
  597. bmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1;
  598.     }
  599. }
  600. Tk_CanvasDrawableCoords(canvas,
  601. (double) (bmapPtr->header.x1 + bmapX),
  602. (double) (bmapPtr->header.y1 + bmapY),
  603. &drawableX, &drawableY);
  604. /*
  605.  * Must modify the mask origin within the graphics context
  606.  * to line up with the bitmap's origin (in order to make
  607.  * bitmaps with "-background {}" work right).
  608.  */
  609. XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,
  610. drawableY - bmapY);
  611. XCopyPlane(display, bitmap, drawable,
  612. bmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth,
  613. (unsigned int) bmapHeight, drawableX, drawableY, 1);
  614. XSetClipOrigin(display, bmapPtr->gc, 0, 0);
  615.     }
  616. }
  617. /*
  618.  *--------------------------------------------------------------
  619.  *
  620.  * BitmapToPoint --
  621.  *
  622.  * Computes the distance from a given point to a given
  623.  * rectangle, in canvas units.
  624.  *
  625.  * Results:
  626.  * The return value is 0 if the point whose x and y coordinates
  627.  * are coordPtr[0] and coordPtr[1] is inside the bitmap.  If the
  628.  * point isn't inside the bitmap then the return value is the
  629.  * distance from the point to the bitmap.
  630.  *
  631.  * Side effects:
  632.  * None.
  633.  *
  634.  *--------------------------------------------------------------
  635.  */
  636. /* ARGSUSED */
  637. static double
  638. BitmapToPoint(canvas, itemPtr, coordPtr)
  639.     Tk_Canvas canvas; /* Canvas containing item. */
  640.     Tk_Item *itemPtr; /* Item to check against point. */
  641.     double *coordPtr; /* Pointer to x and y coordinates. */
  642. {
  643.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  644.     double x1, x2, y1, y2, xDiff, yDiff;
  645.     x1 = bmapPtr->header.x1;
  646.     y1 = bmapPtr->header.y1;
  647.     x2 = bmapPtr->header.x2;
  648.     y2 = bmapPtr->header.y2;
  649.     /*
  650.      * Point is outside rectangle.
  651.      */
  652.     if (coordPtr[0] < x1) {
  653. xDiff = x1 - coordPtr[0];
  654.     } else if (coordPtr[0] > x2)  {
  655. xDiff = coordPtr[0] - x2;
  656.     } else {
  657. xDiff = 0;
  658.     }
  659.     if (coordPtr[1] < y1) {
  660. yDiff = y1 - coordPtr[1];
  661.     } else if (coordPtr[1] > y2)  {
  662. yDiff = coordPtr[1] - y2;
  663.     } else {
  664. yDiff = 0;
  665.     }
  666.     return hypot(xDiff, yDiff);
  667. }
  668. /*
  669.  *--------------------------------------------------------------
  670.  *
  671.  * BitmapToArea --
  672.  *
  673.  * This procedure is called to determine whether an item
  674.  * lies entirely inside, entirely outside, or overlapping
  675.  * a given rectangle.
  676.  *
  677.  * Results:
  678.  * -1 is returned if the item is entirely outside the area
  679.  * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  680.  * inside the given area.
  681.  *
  682.  * Side effects:
  683.  * None.
  684.  *
  685.  *--------------------------------------------------------------
  686.  */
  687. /* ARGSUSED */
  688. static int
  689. BitmapToArea(canvas, itemPtr, rectPtr)
  690.     Tk_Canvas canvas; /* Canvas containing item. */
  691.     Tk_Item *itemPtr; /* Item to check against rectangle. */
  692.     double *rectPtr; /* Pointer to array of four coordinates
  693.  * (x1, y1, x2, y2) describing rectangular
  694.  * area.  */
  695. {
  696.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  697.     if ((rectPtr[2] <= bmapPtr->header.x1)
  698.     || (rectPtr[0] >= bmapPtr->header.x2)
  699.     || (rectPtr[3] <= bmapPtr->header.y1)
  700.     || (rectPtr[1] >= bmapPtr->header.y2)) {
  701. return -1;
  702.     }
  703.     if ((rectPtr[0] <= bmapPtr->header.x1)
  704.     && (rectPtr[1] <= bmapPtr->header.y1)
  705.     && (rectPtr[2] >= bmapPtr->header.x2)
  706.     && (rectPtr[3] >= bmapPtr->header.y2)) {
  707. return 1;
  708.     }
  709.     return 0;
  710. }
  711. /*
  712.  *--------------------------------------------------------------
  713.  *
  714.  * ScaleBitmap --
  715.  *
  716.  * This procedure is invoked to rescale a bitmap item in a
  717.  * canvas.  It is one of the standard item procedures for
  718.  * bitmap items, and is invoked by the generic canvas code.
  719.  *
  720.  * Results:
  721.  * None.
  722.  *
  723.  * Side effects:
  724.  * The item referred to by itemPtr is rescaled so that the
  725.  * following transformation is applied to all point coordinates:
  726.  * x' = originX + scaleX*(x-originX)
  727.  * y' = originY + scaleY*(y-originY)
  728.  *
  729.  *--------------------------------------------------------------
  730.  */
  731. static void
  732. ScaleBitmap(canvas, itemPtr, originX, originY, scaleX, scaleY)
  733.     Tk_Canvas canvas; /* Canvas containing rectangle. */
  734.     Tk_Item *itemPtr; /* Rectangle to be scaled. */
  735.     double originX, originY; /* Origin about which to scale item. */
  736.     double scaleX; /* Amount to scale in X direction. */
  737.     double scaleY; /* Amount to scale in Y direction. */
  738. {
  739.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  740.     bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);
  741.     bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);
  742.     ComputeBitmapBbox(canvas, bmapPtr);
  743. }
  744. /*
  745.  *--------------------------------------------------------------
  746.  *
  747.  * TranslateBitmap --
  748.  *
  749.  * This procedure is called to move an item by a given amount.
  750.  *
  751.  * Results:
  752.  * None.
  753.  *
  754.  * Side effects:
  755.  * The position of the item is offset by (xDelta, yDelta), and
  756.  * the bounding box is updated in the generic part of the item
  757.  * structure.
  758.  *
  759.  *--------------------------------------------------------------
  760.  */
  761. static void
  762. TranslateBitmap(canvas, itemPtr, deltaX, deltaY)
  763.     Tk_Canvas canvas; /* Canvas containing item. */
  764.     Tk_Item *itemPtr; /* Item that is being moved. */
  765.     double deltaX, deltaY; /* Amount by which item is to be
  766.  * moved. */
  767. {
  768.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  769.     bmapPtr->x += deltaX;
  770.     bmapPtr->y += deltaY;
  771.     ComputeBitmapBbox(canvas, bmapPtr);
  772. }
  773. /*
  774.  *--------------------------------------------------------------
  775.  *
  776.  * BitmapToPostscript --
  777.  *
  778.  * This procedure is called to generate Postscript for
  779.  * bitmap items.
  780.  *
  781.  * Results:
  782.  * The return value is a standard Tcl result.  If an error
  783.  * occurs in generating Postscript then an error message is
  784.  * left in the interp's result, replacing whatever used to be there.
  785.  * If no error occurs, then Postscript for the item is appended
  786.  * to the result.
  787.  *
  788.  * Side effects:
  789.  * None.
  790.  *
  791.  *--------------------------------------------------------------
  792.  */
  793. static int
  794. BitmapToPostscript(interp, canvas, itemPtr, prepass)
  795.     Tcl_Interp *interp; /* Leave Postscript or error message
  796.  * here. */
  797.     Tk_Canvas canvas; /* Information about overall canvas. */
  798.     Tk_Item *itemPtr; /* Item for which Postscript is
  799.  * wanted. */
  800.     int prepass; /* 1 means this is a prepass to
  801.  * collect font information;  0 means
  802.  * final Postscript is being created. */
  803. {
  804.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  805.     double x, y;
  806.     int width, height, rowsAtOnce, rowsThisTime;
  807.     int curRow;
  808.     char buffer[100 + TCL_DOUBLE_SPACE * 2 + TCL_INTEGER_SPACE * 4];
  809.     XColor *fgColor;
  810.     XColor *bgColor;
  811.     Pixmap bitmap;
  812.     Tk_State state = itemPtr->state;
  813.     if (state == TK_STATE_NULL) {
  814. state = ((TkCanvas *)canvas)->canvas_state;
  815.     }
  816.     fgColor = bmapPtr->fgColor;
  817.     bgColor = bmapPtr->bgColor;
  818.     bitmap = bmapPtr->bitmap;
  819.     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
  820. if (bmapPtr->activeFgColor!=NULL) {
  821.     fgColor = bmapPtr->activeFgColor;
  822. }
  823. if (bmapPtr->activeBgColor!=NULL) {
  824.     bgColor = bmapPtr->activeBgColor;
  825. }
  826. if (bmapPtr->activeBitmap!=None) {
  827.     bitmap = bmapPtr->activeBitmap;
  828. }
  829.     } else if (state == TK_STATE_DISABLED) {
  830. if (bmapPtr->disabledFgColor!=NULL) {
  831.     fgColor = bmapPtr->disabledFgColor;
  832. }
  833. if (bmapPtr->disabledBgColor!=NULL) {
  834.     bgColor = bmapPtr->disabledBgColor;
  835. }
  836. if (bmapPtr->disabledBitmap!=None) {
  837.     bitmap = bmapPtr->disabledBitmap;
  838. }
  839.     }
  840.     if (bitmap == None) {
  841. return TCL_OK;
  842.     }
  843.     /*
  844.      * Compute the coordinates of the lower-left corner of the bitmap,
  845.      * taking into account the anchor position for the bitmp.
  846.      */
  847.     x = bmapPtr->x;
  848.     y = Tk_CanvasPsY(canvas, bmapPtr->y);
  849.     Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap,
  850.     &width, &height);
  851.     switch (bmapPtr->anchor) {
  852. case TK_ANCHOR_NW: y -= height; break;
  853. case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
  854. case TK_ANCHOR_NE: x -= width; y -= height; break;
  855. case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
  856. case TK_ANCHOR_SE: x -= width; break;
  857. case TK_ANCHOR_S: x -= width/2.0; break;
  858. case TK_ANCHOR_SW: break;
  859. case TK_ANCHOR_W: y -= height/2.0; break;
  860. case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
  861.     }
  862.     /*
  863.      * Color the background, if there is one.
  864.      */
  865.     if (bgColor != NULL) {
  866. sprintf(buffer,
  867. "%.15g %.15g moveto %d 0 rlineto 0 %d rlineto %d %sn",
  868. x, y, width, height, -width, "0 rlineto closepath");
  869. Tcl_AppendResult(interp, buffer, (char *) NULL);
  870. if (Tk_CanvasPsColor(interp, canvas, bgColor) != TCL_OK) {
  871.     return TCL_ERROR;
  872. }
  873. Tcl_AppendResult(interp, "filln", (char *) NULL);
  874.     }
  875.     /*
  876.      * Draw the bitmap, if there is a foreground color.  If the bitmap
  877.      * is very large, then chop it up into multiple bitmaps, each
  878.      * consisting of one or more rows.  This is needed because Postscript
  879.      * can't handle single strings longer than 64 KBytes long.
  880.      */
  881.     if (fgColor != NULL) {
  882. if (Tk_CanvasPsColor(interp, canvas, fgColor) != TCL_OK) {
  883.     return TCL_ERROR;
  884. }
  885. if (width > 60000) {
  886.     Tcl_ResetResult(interp);
  887.     Tcl_AppendResult(interp, "can't generate Postscript",
  888.     " for bitmaps more than 60000 pixels wide",
  889.     (char *) NULL);
  890.     return TCL_ERROR;
  891. }
  892. rowsAtOnce = 60000/width;
  893. if (rowsAtOnce < 1) {
  894.     rowsAtOnce = 1;
  895. }
  896. sprintf(buffer, "%.15g %.15g translaten", x, y+height);
  897. Tcl_AppendResult(interp, buffer, (char *) NULL);
  898. for (curRow = 0; curRow < height; curRow += rowsAtOnce) {
  899.     rowsThisTime = rowsAtOnce;
  900.     if (rowsThisTime > (height - curRow)) {
  901. rowsThisTime = height - curRow;
  902.     }
  903.     sprintf(buffer, "0 -%.15g translaten%d %d true matrix {n",
  904.     (double) rowsThisTime, width, rowsThisTime);
  905.     Tcl_AppendResult(interp, buffer, (char *) NULL);
  906.     if (Tk_CanvasPsBitmap(interp, canvas, bitmap,
  907.     0, curRow, width, rowsThisTime) != TCL_OK) {
  908. return TCL_ERROR;
  909.     }
  910.     Tcl_AppendResult(interp, "n} imagemaskn", (char *) NULL);
  911. }
  912.     }
  913.     return TCL_OK;
  914. }