home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tkisrc04.zip / tk / os2 / tkCanvBmap.c < prev    next >
C/C++ Source or Header  |  1998-08-07  |  23KB  |  801 lines

  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-1995 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.  * SCCS: @(#) tkCanvBmap.c 1.29 96/02/17 16:59:10
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "tkInt.h"
  17. #include "tkPort.h"
  18. #include "tkCanvas.h"
  19.  
  20. /*
  21.  * The structure below defines the record for each bitmap item.
  22.  */
  23.  
  24. typedef struct BitmapItem  {
  25.     Tk_Item header;        /* Generic stuff that's the same for all
  26.                  * types.  MUST BE FIRST IN STRUCTURE. */
  27.     double x, y;        /* Coordinates of positioning point for
  28.                  * bitmap. */
  29.     Tk_Anchor anchor;        /* Where to anchor bitmap relative to
  30.                  * (x,y). */
  31.     Pixmap bitmap;        /* Bitmap to display in window. */
  32.     XColor *fgColor;        /* Foreground color to use for bitmap. */
  33.     XColor *bgColor;        /* Background color to use for bitmap. */
  34.     GC gc;            /* Graphics context to use for drawing
  35.                  * bitmap on screen. */
  36. } BitmapItem;
  37.  
  38. /*
  39.  * Information used for parsing configuration specs:
  40.  */
  41.  
  42. static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
  43.     Tk_CanvasTagsPrintProc, (ClientData) NULL
  44. };
  45.  
  46. static Tk_ConfigSpec configSpecs[] = {
  47.     {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
  48.     "center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
  49.     {TK_CONFIG_COLOR, "-background", (char *) NULL, (char *) NULL,
  50.     (char *) NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK},
  51.     {TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
  52.     (char *) NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK},
  53.     {TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL,
  54.     "black", Tk_Offset(BitmapItem, fgColor), 0},
  55.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  56.     (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
  57.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  58.     (char *) NULL, 0, 0}
  59. };
  60.  
  61. /*
  62.  * Prototypes for procedures defined in this file:
  63.  */
  64.  
  65. static int        BitmapCoords _ANSI_ARGS_((Tcl_Interp *interp,
  66.                 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  67.                 char **argv));
  68. static int        BitmapToArea _ANSI_ARGS_((Tk_Canvas canvas,
  69.                 Tk_Item *itemPtr, double *rectPtr));
  70. static double        BitmapToPoint _ANSI_ARGS_((Tk_Canvas canvas,
  71.                 Tk_Item *itemPtr, double *coordPtr));
  72. static int        BitmapToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
  73.                 Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
  74. static void        ComputeBitmapBbox _ANSI_ARGS_((Tk_Canvas canvas,
  75.                 BitmapItem *bmapPtr));
  76. static int        ConfigureBitmap _ANSI_ARGS_((Tcl_Interp *interp,
  77.                 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  78.                 char **argv, int flags));
  79. static int        CreateBitmap _ANSI_ARGS_((Tcl_Interp *interp,
  80.                 Tk_Canvas canvas, struct Tk_Item *itemPtr,
  81.                 int argc, char **argv));
  82. static void        DeleteBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  83.                 Tk_Item *itemPtr, Display *display));
  84. static void        DisplayBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  85.                 Tk_Item *itemPtr, Display *display, Drawable dst,
  86.                 int x, int y, int width, int height));
  87. static void        ScaleBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  88.                 Tk_Item *itemPtr, double originX, double originY,
  89.                 double scaleX, double scaleY));
  90. static void        TranslateBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  91.                 Tk_Item *itemPtr, double deltaX, double deltaY));
  92.  
  93. /*
  94.  * The structures below defines the bitmap item type in terms of
  95.  * 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.     BitmapToPostscript,            /* postscriptProc */
  111.     ScaleBitmap,            /* scaleProc */
  112.     TranslateBitmap,            /* translateProc */
  113.     (Tk_ItemIndexProc *) NULL,        /* indexProc */
  114.     (Tk_ItemCursorProc *) NULL,        /* icursorProc */
  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.  *    interp->result;  in this case itemPtr is left uninitialized,
  133.  *    so it can be safely freed by the caller.
  134.  *
  135.  * Side effects:
  136.  *    A new bitmap item is created.
  137.  *
  138.  *--------------------------------------------------------------
  139.  */
  140.  
  141. static int
  142. CreateBitmap(interp, canvas, itemPtr, argc, argv)
  143.     Tcl_Interp *interp;            /* Interpreter for error reporting. */
  144.     Tk_Canvas canvas;            /* 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.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  151.  
  152.     if (argc < 2) {
  153.     Tcl_AppendResult(interp, "wrong # args: should be \"",
  154.         Tk_PathName(Tk_CanvasTkwin(canvas)), " 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 ((Tk_CanvasGetCoord(interp, canvas, argv[0], &bmapPtr->x) != TCL_OK)
  175.         || (Tk_CanvasGetCoord(interp, canvas, argv[1], &bmapPtr->y)
  176.         != TCL_OK)) {
  177.     return TCL_ERROR;
  178.     }
  179.  
  180.     if (ConfigureBitmap(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
  181.     DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
  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 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(interp, canvas, itemPtr, argc, argv)
  207.     Tcl_Interp *interp;            /* Used for error reporting. */
  208.     Tk_Canvas canvas;            /* 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
  212.                      * argv. */
  213.     char **argv;            /* Array of coordinates: x1, y1,
  214.                      * x2, y2, ... */
  215. {
  216.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  217.     char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
  218.  
  219.     if (argc == 0) {
  220.     Tcl_PrintDouble(interp, bmapPtr->x, x);
  221.     Tcl_PrintDouble(interp, bmapPtr->y, y);
  222.     Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
  223.     } else if (argc == 2) {
  224.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &bmapPtr->x) != TCL_OK)
  225.         || (Tk_CanvasGetCoord(interp, canvas, argv[1], &bmapPtr->y)
  226.             != TCL_OK)) {
  227.         return TCL_ERROR;
  228.     }
  229.     ComputeBitmapBbox(canvas, bmapPtr);
  230.     } else {
  231.     sprintf(interp->result,
  232.         "wrong # coordinates: expected 0 or 2, got %d", argc);
  233.     return TCL_ERROR;
  234.     }
  235.     return TCL_OK;
  236. }
  237.  
  238. /*
  239.  *--------------------------------------------------------------
  240.  *
  241.  * ConfigureBitmap --
  242.  *
  243.  *    This procedure is invoked to configure various aspects
  244.  *    of a bitmap item, such as its anchor position.
  245.  *
  246.  * Results:
  247.  *    A standard Tcl result code.  If an error occurs, then
  248.  *    an error message is left in interp->result.
  249.  *
  250.  * Side effects:
  251.  *    Configuration information may be set for itemPtr.
  252.  *
  253.  *--------------------------------------------------------------
  254.  */
  255.  
  256. static int
  257. ConfigureBitmap(interp, canvas, itemPtr, argc, argv, flags)
  258.     Tcl_Interp *interp;        /* Used for error reporting. */
  259.     Tk_Canvas canvas;        /* Canvas containing itemPtr. */
  260.     Tk_Item *itemPtr;        /* Bitmap item to reconfigure. */
  261.     int argc;            /* Number of elements in argv.  */
  262.     char **argv;        /* Arguments describing things to configure. */
  263.     int flags;            /* Flags to pass to Tk_ConfigureWidget. */
  264. {
  265.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  266.     XGCValues gcValues;
  267.     GC newGC;
  268.     Tk_Window tkwin;
  269.     unsigned long mask;
  270.  
  271.     tkwin = Tk_CanvasTkwin(canvas);
  272.     if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
  273.         (char *) bmapPtr, flags) != TCL_OK) {
  274.     return TCL_ERROR;
  275.     }
  276.  
  277.     /*
  278.      * A few of the options require additional processing, such as those
  279.      * that determine the graphics context.
  280.      */
  281.  
  282.     gcValues.foreground = bmapPtr->fgColor->pixel;
  283.     mask = GCForeground;
  284.     if (bmapPtr->bgColor != NULL) {
  285.     gcValues.background = bmapPtr->bgColor->pixel;
  286.     mask |= GCBackground;
  287.     } else {
  288.     gcValues.clip_mask = bmapPtr->bitmap;
  289.     mask |= GCClipMask;
  290.     }
  291.     newGC = Tk_GetGC(tkwin, mask, &gcValues);
  292.     if (bmapPtr->gc != None) {
  293.     Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
  294.     }
  295.     bmapPtr->gc = newGC;
  296.  
  297.     ComputeBitmapBbox(canvas, bmapPtr);
  298.  
  299.     return TCL_OK;
  300. }
  301.  
  302. /*
  303.  *--------------------------------------------------------------
  304.  *
  305.  * DeleteBitmap --
  306.  *
  307.  *    This procedure is called to clean up the data structure
  308.  *    associated with a bitmap item.
  309.  *
  310.  * Results:
  311.  *    None.
  312.  *
  313.  * Side effects:
  314.  *    Resources associated with itemPtr are released.
  315.  *
  316.  *--------------------------------------------------------------
  317.  */
  318.  
  319. static void
  320. DeleteBitmap(canvas, itemPtr, display)
  321.     Tk_Canvas canvas;            /* Info about overall canvas widget. */
  322.     Tk_Item *itemPtr;            /* Item that is being deleted. */
  323.     Display *display;            /* Display containing window for
  324.                      * canvas. */
  325. {
  326.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  327.  
  328.     if (bmapPtr->bitmap != None) {
  329.     Tk_FreeBitmap(display, bmapPtr->bitmap);
  330.     }
  331.     if (bmapPtr->fgColor != NULL) {
  332.     Tk_FreeColor(bmapPtr->fgColor);
  333.     }
  334.     if (bmapPtr->bgColor != NULL) {
  335.     Tk_FreeColor(bmapPtr->bgColor);
  336.     }
  337.     if (bmapPtr->gc != NULL) {
  338.     Tk_FreeGC(display, bmapPtr->gc);
  339.     }
  340. }
  341.  
  342. /*
  343.  *--------------------------------------------------------------
  344.  *
  345.  * ComputeBitmapBbox --
  346.  *
  347.  *    This procedure is invoked to compute the bounding box of
  348.  *    all the pixels that may be drawn as part of a bitmap item.
  349.  *    This procedure is where the child bitmap's placement is
  350.  *    computed.
  351.  *
  352.  * Results:
  353.  *    None.
  354.  *
  355.  * Side effects:
  356.  *    The fields x1, y1, x2, and y2 are updated in the header
  357.  *    for itemPtr.
  358.  *
  359.  *--------------------------------------------------------------
  360.  */
  361.  
  362.     /* ARGSUSED */
  363. static void
  364. ComputeBitmapBbox(canvas, bmapPtr)
  365.     Tk_Canvas canvas;            /* Canvas that contains item. */
  366.     BitmapItem *bmapPtr;        /* Item whose bbox is to be
  367.                      * recomputed. */
  368. {
  369.     int width, height;
  370.     int x, y;
  371.  
  372.     x = bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5);
  373.     y = bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5);
  374.  
  375.     if (bmapPtr->bitmap == None) {
  376.     bmapPtr->header.x1 = bmapPtr->header.x2 = x;
  377.     bmapPtr->header.y1 = bmapPtr->header.y2 = y;
  378.     return;
  379.     }
  380.  
  381.     /*
  382.      * Compute location and size of bitmap, using anchor information.
  383.      */
  384.  
  385.     Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bmapPtr->bitmap,
  386.         &width, &height);
  387.     switch (bmapPtr->anchor) {
  388.     case TK_ANCHOR_N:
  389.         x -= width/2;
  390.         break;
  391.     case TK_ANCHOR_NE:
  392.         x -= width;
  393.         break;
  394.     case TK_ANCHOR_E:
  395.         x -= width;
  396.         y -= height/2;
  397.         break;
  398.     case TK_ANCHOR_SE:
  399.         x -= width;
  400.         y -= height;
  401.         break;
  402.     case TK_ANCHOR_S:
  403.         x -= width/2;
  404.         y -= height;
  405.         break;
  406.     case TK_ANCHOR_SW:
  407.         y -= height;
  408.         break;
  409.     case TK_ANCHOR_W:
  410.         y -= height/2;
  411.         break;
  412.     case TK_ANCHOR_NW:
  413.         break;
  414.     case TK_ANCHOR_CENTER:
  415.         x -= width/2;
  416.         y -= height/2;
  417.         break;
  418.     }
  419.  
  420.     /*
  421.      * Store the information in the item header.
  422.      */
  423.  
  424.     bmapPtr->header.x1 = x;
  425.     bmapPtr->header.y1 = y;
  426.     bmapPtr->header.x2 = x + width;
  427.     bmapPtr->header.y2 = y + height;
  428. }
  429.  
  430. /*
  431.  *--------------------------------------------------------------
  432.  *
  433.  * DisplayBitmap --
  434.  *
  435.  *    This procedure is invoked to draw a bitmap item in a given
  436.  *    drawable.
  437.  *
  438.  * Results:
  439.  *    None.
  440.  *
  441.  * Side effects:
  442.  *    ItemPtr is drawn in drawable using the transformation
  443.  *    information in canvas.
  444.  *
  445.  *--------------------------------------------------------------
  446.  */
  447.  
  448. static void
  449. DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height)
  450.     Tk_Canvas canvas;            /* Canvas that contains item. */
  451.     Tk_Item *itemPtr;            /* Item to be displayed. */
  452.     Display *display;            /* Display on which to draw item. */
  453.     Drawable drawable;            /* Pixmap or window in which to draw
  454.                      * item. */
  455.     int x, y, width, height;        /* Describes region of canvas that
  456.                      * must be redisplayed (not used). */
  457. {
  458.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  459.     int bmapX, bmapY, bmapWidth, bmapHeight;
  460.     short drawableX, drawableY;
  461.  
  462.     /*
  463.      * If the area being displayed doesn't cover the whole bitmap,
  464.      * then only redisplay the part of the bitmap that needs
  465.      * redisplay.
  466.      */
  467.  
  468.     if (bmapPtr->bitmap != None) {
  469.     if (x > bmapPtr->header.x1) {
  470.         bmapX = x - bmapPtr->header.x1;
  471.         bmapWidth = bmapPtr->header.x2 - x;
  472.     } else {
  473.         bmapX = 0;
  474.         if ((x+width) < bmapPtr->header.x2) {
  475.         bmapWidth = x + width - bmapPtr->header.x1;
  476.         } else {
  477.         bmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1;
  478.         }
  479.     }
  480.     if (y > bmapPtr->header.y1) {
  481.         bmapY = y - bmapPtr->header.y1;
  482.         bmapHeight = bmapPtr->header.y2 - y;
  483.     } else {
  484.         bmapY = 0;
  485.         if ((y+height) < bmapPtr->header.y2) {
  486.         bmapHeight = y + height - bmapPtr->header.y1;
  487.         } else {
  488.         bmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1;
  489.         }
  490.     }
  491.     Tk_CanvasDrawableCoords(canvas,
  492.         (double) (bmapPtr->header.x1 + bmapX),
  493.         (double) (bmapPtr->header.y1 + bmapY),
  494.         &drawableX, &drawableY);
  495.  
  496.     /*
  497.      * Must modify the mask origin within the graphics context
  498.      * to line up with the bitmap's origin (in order to make
  499.      * bitmaps with "-background {}" work right).
  500.      */
  501.  
  502.     XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,
  503.         drawableY - bmapY);
  504.     XCopyPlane(display, bmapPtr->bitmap, drawable,
  505.         bmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth,
  506.         (unsigned int) bmapHeight, drawableX, drawableY, 1);
  507.     }
  508. }
  509.  
  510. /*
  511.  *--------------------------------------------------------------
  512.  *
  513.  * BitmapToPoint --
  514.  *
  515.  *    Computes the distance from a given point to a given
  516.  *    rectangle, in canvas units.
  517.  *
  518.  * Results:
  519.  *    The return value is 0 if the point whose x and y coordinates
  520.  *    are coordPtr[0] and coordPtr[1] is inside the bitmap.  If the
  521.  *    point isn't inside the bitmap then the return value is the
  522.  *    distance from the point to the bitmap.
  523.  *
  524.  * Side effects:
  525.  *    None.
  526.  *
  527.  *--------------------------------------------------------------
  528.  */
  529.  
  530.     /* ARGSUSED */
  531. static double
  532. BitmapToPoint(canvas, itemPtr, coordPtr)
  533.     Tk_Canvas canvas;        /* Canvas containing item. */
  534.     Tk_Item *itemPtr;        /* Item to check against point. */
  535.     double *coordPtr;        /* Pointer to x and y coordinates. */
  536. {
  537.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  538.     double x1, x2, y1, y2, xDiff, yDiff;
  539.  
  540.     x1 = bmapPtr->header.x1;
  541.     y1 = bmapPtr->header.y1;
  542.     x2 = bmapPtr->header.x2;
  543.     y2 = bmapPtr->header.y2;
  544.  
  545.     /*
  546.      * Point is outside rectangle.
  547.      */
  548.  
  549.     if (coordPtr[0] < x1) {
  550.     xDiff = x1 - coordPtr[0];
  551.     } else if (coordPtr[0] > x2)  {
  552.     xDiff = coordPtr[0] - x2;
  553.     } else {
  554.     xDiff = 0;
  555.     }
  556.  
  557.     if (coordPtr[1] < y1) {
  558.     yDiff = y1 - coordPtr[1];
  559.     } else if (coordPtr[1] > y2)  {
  560.     yDiff = coordPtr[1] - y2;
  561.     } else {
  562.     yDiff = 0;
  563.     }
  564.  
  565.     return hypot(xDiff, yDiff);
  566. }
  567.  
  568. /*
  569.  *--------------------------------------------------------------
  570.  *
  571.  * BitmapToArea --
  572.  *
  573.  *    This procedure is called to determine whether an item
  574.  *    lies entirely inside, entirely outside, or overlapping
  575.  *    a given rectangle.
  576.  *
  577.  * Results:
  578.  *    -1 is returned if the item is entirely outside the area
  579.  *    given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  580.  *    inside the given area.
  581.  *
  582.  * Side effects:
  583.  *    None.
  584.  *
  585.  *--------------------------------------------------------------
  586.  */
  587.  
  588.     /* ARGSUSED */
  589. static int
  590. BitmapToArea(canvas, itemPtr, rectPtr)
  591.     Tk_Canvas canvas;        /* Canvas containing item. */
  592.     Tk_Item *itemPtr;        /* Item to check against rectangle. */
  593.     double *rectPtr;        /* Pointer to array of four coordinates
  594.                  * (x1, y1, x2, y2) describing rectangular
  595.                  * area.  */
  596. {
  597.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  598.  
  599.     if ((rectPtr[2] <= bmapPtr->header.x1)
  600.         || (rectPtr[0] >= bmapPtr->header.x2)
  601.         || (rectPtr[3] <= bmapPtr->header.y1)
  602.         || (rectPtr[1] >= bmapPtr->header.y2)) {
  603.     return -1;
  604.     }
  605.     if ((rectPtr[0] <= bmapPtr->header.x1)
  606.         && (rectPtr[1] <= bmapPtr->header.y1)
  607.         && (rectPtr[2] >= bmapPtr->header.x2)
  608.         && (rectPtr[3] >= bmapPtr->header.y2)) {
  609.     return 1;
  610.     }
  611.     return 0;
  612. }
  613.  
  614. /*
  615.  *--------------------------------------------------------------
  616.  *
  617.  * ScaleBitmap --
  618.  *
  619.  *    This procedure is invoked to rescale a bitmap item in a
  620.  *    canvas.  It is one of the standard item procedures for
  621.  *    bitmap items, and is invoked by the generic canvas code.
  622.  *
  623.  * Results:
  624.  *    None.
  625.  *
  626.  * Side effects:
  627.  *    The item referred to by itemPtr is rescaled so that the
  628.  *    following transformation is applied to all point coordinates:
  629.  *        x' = originX + scaleX*(x-originX)
  630.  *        y' = originY + scaleY*(y-originY)
  631.  *
  632.  *--------------------------------------------------------------
  633.  */
  634.  
  635. static void
  636. ScaleBitmap(canvas, itemPtr, originX, originY, scaleX, scaleY)
  637.     Tk_Canvas canvas;            /* Canvas containing rectangle. */
  638.     Tk_Item *itemPtr;            /* Rectangle to be scaled. */
  639.     double originX, originY;        /* Origin about which to scale item. */
  640.     double scaleX;            /* Amount to scale in X direction. */
  641.     double scaleY;            /* Amount to scale in Y direction. */
  642. {
  643.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  644.  
  645.     bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);
  646.     bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);
  647.     ComputeBitmapBbox(canvas, bmapPtr);
  648. }
  649.  
  650. /*
  651.  *--------------------------------------------------------------
  652.  *
  653.  * TranslateBitmap --
  654.  *
  655.  *    This procedure is called to move an item by a given amount.
  656.  *
  657.  * Results:
  658.  *    None.
  659.  *
  660.  * Side effects:
  661.  *    The position of the item is offset by (xDelta, yDelta), and
  662.  *    the bounding box is updated in the generic part of the item
  663.  *    structure.
  664.  *
  665.  *--------------------------------------------------------------
  666.  */
  667.  
  668. static void
  669. TranslateBitmap(canvas, itemPtr, deltaX, deltaY)
  670.     Tk_Canvas canvas;            /* Canvas containing item. */
  671.     Tk_Item *itemPtr;            /* Item that is being moved. */
  672.     double deltaX, deltaY;        /* Amount by which item is to be
  673.                      * moved. */
  674. {
  675.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  676.  
  677.     bmapPtr->x += deltaX;
  678.     bmapPtr->y += deltaY;
  679.     ComputeBitmapBbox(canvas, bmapPtr);
  680. }
  681.  
  682. /*
  683.  *--------------------------------------------------------------
  684.  *
  685.  * BitmapToPostscript --
  686.  *
  687.  *    This procedure is called to generate Postscript for
  688.  *    bitmap items.
  689.  *
  690.  * Results:
  691.  *    The return value is a standard Tcl result.  If an error
  692.  *    occurs in generating Postscript then an error message is
  693.  *    left in interp->result, replacing whatever used to be there.
  694.  *    If no error occurs, then Postscript for the item is appended
  695.  *    to the result.
  696.  *
  697.  * Side effects:
  698.  *    None.
  699.  *
  700.  *--------------------------------------------------------------
  701.  */
  702.  
  703. static int
  704. BitmapToPostscript(interp, canvas, itemPtr, prepass)
  705.     Tcl_Interp *interp;            /* Leave Postscript or error message
  706.                      * here. */
  707.     Tk_Canvas canvas;            /* Information about overall canvas. */
  708.     Tk_Item *itemPtr;            /* Item for which Postscript is
  709.                      * wanted. */
  710.     int prepass;            /* 1 means this is a prepass to
  711.                      * collect font information;  0 means
  712.                      * final Postscript is being created. */
  713. {
  714.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  715.     double x, y;
  716.     int width, height, rowsAtOnce, rowsThisTime;
  717.     int curRow;
  718.     char buffer[200];
  719.  
  720.     if (bmapPtr->bitmap == None) {
  721.     return TCL_OK;
  722.     }
  723.  
  724.     /*
  725.      * Compute the coordinates of the lower-left corner of the bitmap,
  726.      * taking into account the anchor position for the bitmp.
  727.      */
  728.  
  729.     x = bmapPtr->x;
  730.     y = Tk_CanvasPsY(canvas, bmapPtr->y);
  731.     Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bmapPtr->bitmap,
  732.         &width, &height);
  733.     switch (bmapPtr->anchor) {
  734.     case TK_ANCHOR_NW:            y -= height;        break;
  735.     case TK_ANCHOR_N:    x -= width/2.0; y -= height;        break;
  736.     case TK_ANCHOR_NE:    x -= width;    y -= height;        break;
  737.     case TK_ANCHOR_E:    x -= width;    y -= height/2.0;    break;
  738.     case TK_ANCHOR_SE:    x -= width;                break;
  739.     case TK_ANCHOR_S:    x -= width/2.0;                break;
  740.     case TK_ANCHOR_SW:                        break;
  741.     case TK_ANCHOR_W:            y -= height/2.0;    break;
  742.     case TK_ANCHOR_CENTER:    x -= width/2.0; y -= height/2.0;    break;
  743.     }
  744.  
  745.     /*
  746.      * Color the background, if there is one.
  747.      */
  748.  
  749.     if (bmapPtr->bgColor != NULL) {
  750.     sprintf(buffer,
  751.         "%.15g %.15g moveto %d 0 rlineto 0 %d rlineto %d %s\n",
  752.         x, y, width, height, -width,"0 rlineto closepath");
  753.     Tcl_AppendResult(interp, buffer, (char *) NULL);
  754.     if (Tk_CanvasPsColor(interp, canvas, bmapPtr->bgColor) != TCL_OK) {
  755.         return TCL_ERROR;
  756.     }
  757.     Tcl_AppendResult(interp, "fill\n", (char *) NULL);
  758.     }
  759.  
  760.     /*
  761.      * Draw the bitmap, if there is a foreground color.  If the bitmap
  762.      * is very large, then chop it up into multiple bitmaps, each
  763.      * consisting of one or more rows.  This is needed because Postscript
  764.      * can't handle single strings longer than 64 KBytes long.
  765.      */
  766.  
  767.     if (bmapPtr->fgColor != NULL) {
  768.     if (Tk_CanvasPsColor(interp, canvas, bmapPtr->fgColor) != TCL_OK) {
  769.         return TCL_ERROR;
  770.     }
  771.     if (width > 60000) {
  772.         Tcl_ResetResult(interp);
  773.         Tcl_AppendResult(interp, "can't generate Postscript",
  774.             " for bitmaps more than 60000 pixels wide",
  775.             (char *) NULL);
  776.         return TCL_ERROR;
  777.     }
  778.     rowsAtOnce = 60000/width;
  779.     if (rowsAtOnce < 1) {
  780.         rowsAtOnce = 1;
  781.     }
  782.     sprintf(buffer, "%.15g %.15g translate\n", x, y+height);
  783.     Tcl_AppendResult(interp, buffer, (char *) NULL);
  784.     for (curRow = 0; curRow < height; curRow += rowsAtOnce) {
  785.         rowsThisTime = rowsAtOnce;
  786.         if (rowsThisTime > (height - curRow)) {
  787.         rowsThisTime = height - curRow;
  788.         }
  789.         sprintf(buffer, "0 -%.15g translate\n%d %d true matrix {\n",
  790.             (double) rowsThisTime, width, rowsThisTime);
  791.         Tcl_AppendResult(interp, buffer, (char *) NULL);
  792.         if (Tk_CanvasPsBitmap(interp, canvas, bmapPtr->bitmap,
  793.             0, curRow, width, rowsThisTime) != TCL_OK) {
  794.         return TCL_ERROR;
  795.         }
  796.         Tcl_AppendResult(interp, "\n} imagemask\n", (char *) NULL);
  797.     }
  798.     }
  799.     return TCL_OK;
  800. }
  801.