home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / mac / tkMacDraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  26.4 KB  |  1,043 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkMacDraw.c --
  3.  *
  4.  *    This file contains functions that preform drawing to
  5.  *    Xlib windows.  Most of the functions simple emulate
  6.  *    Xlib functions.
  7.  *
  8.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * SCCS: @(#) tkMacDraw.c 1.50 97/07/10 13:29:16
  14.  */
  15.  
  16. #include "tkInt.h"
  17. #include "X.h"
  18. #include "Xlib.h"
  19. #include <stdio.h>
  20. #include <tcl.h>
  21.  
  22. #include <Windows.h>
  23. #include <Fonts.h>
  24. #include <QDOffscreen.h>
  25. #include "tkMacInt.h"
  26.  
  27. #ifndef PI
  28. #    define PI 3.14159265358979323846
  29. #endif
  30.  
  31. /*
  32.  * Temporary region that can be reused.
  33.  */
  34. static RgnHandle tmpRgn = NULL;
  35.  
  36. static PixPatHandle gPenPat = NULL;
  37.  
  38. /*
  39.  * Prototypes for functions used only in this file.
  40.  */
  41. static unsigned char    InvertByte _ANSI_ARGS_((unsigned char data));
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * XCopyArea --
  47.  *
  48.  *    Copies data from one drawable to another using block transfer
  49.  *    routines.
  50.  *
  51.  * Results:
  52.  *    None.
  53.  *
  54.  * Side effects:
  55.  *    Data is moved from a window or bitmap to a second window or
  56.  *    bitmap.
  57.  *
  58.  *----------------------------------------------------------------------
  59.  */
  60.  
  61. void 
  62. XCopyArea(
  63.     Display* display,        /* Display. */
  64.     Drawable src,        /* Source drawable. */
  65.     Drawable dest,        /* Destination drawable. */
  66.     GC gc,            /* GC to use. */
  67.     int src_x,            /* X & Y, width & height */
  68.     int src_y,            /* define the source rectangle */
  69.     unsigned int width,        /* the will be copied. */
  70.     unsigned int height,
  71.     int dest_x,            /* Dest X & Y on dest rect. */
  72.     int dest_y)
  73. {
  74.     Rect srcRect, destRect;
  75.     BitMapPtr srcBit, destBit;
  76.     MacDrawable *srcDraw = (MacDrawable *) src;
  77.     MacDrawable *destDraw = (MacDrawable *) dest;
  78.     GWorldPtr srcPort, destPort;
  79.     CGrafPtr saveWorld;
  80.     GDHandle saveDevice;
  81.     short tmode;
  82.     RGBColor origForeColor, origBackColor, whiteColor, blackColor;
  83.  
  84.     destPort = TkMacGetDrawablePort(dest);
  85.     srcPort = TkMacGetDrawablePort(src);
  86.  
  87.     display->request++;
  88.     GetGWorld(&saveWorld, &saveDevice);
  89.     SetGWorld(destPort, NULL);
  90.     GetForeColor(&origForeColor);
  91.     GetBackColor(&origBackColor);
  92.     whiteColor.red = 0;
  93.     whiteColor.blue = 0;
  94.     whiteColor.green = 0;
  95.     RGBForeColor(&whiteColor);
  96.     blackColor.red = 0xFFFF;
  97.     blackColor.blue = 0xFFFF;
  98.     blackColor.green = 0xFFFF;
  99.     RGBBackColor(&blackColor);
  100.     
  101.  
  102.     TkMacSetUpClippingRgn(dest);
  103.  
  104.     srcBit = &((GrafPtr) srcPort)->portBits;
  105.     destBit = &((GrafPtr) destPort)->portBits;
  106.     SetRect(&srcRect, (short) (srcDraw->xOff + src_x),
  107.         (short) (srcDraw->yOff + src_y),
  108.         (short) (srcDraw->xOff + src_x + width),
  109.         (short) (srcDraw->yOff + src_y + height));    
  110.     SetRect(&destRect, (short) (destDraw->xOff + dest_x),
  111.         (short) (destDraw->yOff + dest_y), 
  112.         (short) (destDraw->xOff + dest_x + width),
  113.         (short) (destDraw->yOff + dest_y + height));    
  114.     tmode = srcCopy;
  115.  
  116.     CopyBits(srcBit, destBit, &srcRect, &destRect, tmode, NULL);
  117.     RGBForeColor(&origForeColor);
  118.     RGBBackColor(&origBackColor);
  119.     SetGWorld(saveWorld, saveDevice);
  120. }
  121.  
  122. /*
  123.  *----------------------------------------------------------------------
  124.  *
  125.  * XCopyPlane --
  126.  *
  127.  *    Copies a bitmap from a source drawable to a destination
  128.  *    drawable.  The plane argument specifies which bit plane of
  129.  *    the source contains the bitmap.  Note that this implementation
  130.  *    ignores the gc->function.
  131.  *
  132.  * Results:
  133.  *    None.
  134.  *
  135.  * Side effects:
  136.  *    Changes the destination drawable.
  137.  *
  138.  *----------------------------------------------------------------------
  139.  */
  140.  
  141. void
  142. XCopyPlane(
  143.     Display* display,        /* Display. */
  144.     Drawable src,        /* Source drawable. */
  145.     Drawable dest,        /* Destination drawable. */
  146.     GC gc,            /* The GC to use. */
  147.     int src_x,            /* X, Y, width & height */
  148.     int src_y,            /* define the source rect. */
  149.     unsigned int width,
  150.     unsigned int height,
  151.     int dest_x,            /* X & Y on dest where we will copy. */
  152.     int dest_y,
  153.     unsigned long plane)    /* Which plane to copy. */
  154. {
  155.     Rect srcRect, destRect;
  156.     BitMapPtr srcBit, destBit, maskBit;
  157.     MacDrawable *srcDraw = (MacDrawable *) src;
  158.     MacDrawable *destDraw = (MacDrawable *) dest;
  159.     GWorldPtr srcPort, destPort, maskPort;
  160.     CGrafPtr saveWorld;
  161.     GDHandle saveDevice;
  162.     RGBColor macColor; 
  163.     TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
  164.     short tmode;
  165.  
  166.     destPort = TkMacGetDrawablePort(dest);
  167.     srcPort = TkMacGetDrawablePort(src);
  168.     
  169.     display->request++;
  170.     GetGWorld(&saveWorld, &saveDevice);
  171.     SetGWorld(destPort, NULL);
  172.  
  173.     TkMacSetUpClippingRgn(dest);
  174.  
  175.     srcBit = &((GrafPtr) srcPort)->portBits;
  176.     destBit = &((GrafPtr) destPort)->portBits;
  177.     SetRect(&srcRect, (short) (srcDraw->xOff + src_x),
  178.         (short) (srcDraw->yOff + src_y),
  179.         (short) (srcDraw->xOff + src_x + width),
  180.         (short) (srcDraw->yOff + src_y + height));
  181.     SetRect(&destRect, (short) (destDraw->xOff + dest_x),
  182.         (short) (destDraw->yOff + dest_y), 
  183.         (short) (destDraw->xOff + dest_x + width),
  184.         (short) (destDraw->yOff + dest_y + height));
  185.     tmode = srcOr;
  186.     tmode = srcCopy + transparent;
  187.  
  188.     if (TkSetMacColor(gc->foreground, &macColor) == true) {
  189.     RGBForeColor(&macColor);
  190.     }
  191.  
  192.     if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) {
  193.  
  194.     /*
  195.      * Case 1: opaque bitmaps.
  196.      */
  197.  
  198.     TkSetMacColor(gc->background, &macColor);
  199.     RGBBackColor(&macColor);
  200.     tmode = srcCopy;
  201.     CopyBits(srcBit, destBit, &srcRect, &destRect, tmode, NULL);
  202.     } else if (clipPtr->type == TKP_CLIP_PIXMAP) {
  203.     if (clipPtr->value.pixmap == src) {
  204.         /*
  205.          * Case 2: transparent bitmaps.  If it's color we ignore
  206.          * the forecolor.
  207.          */
  208.         if ((**(srcPort->portPixMap)).pixelSize == 1) {
  209.         tmode = srcOr;
  210.         } else {
  211.         tmode = transparent;
  212.         }
  213.         CopyBits(srcBit, destBit, &srcRect, &destRect, tmode, NULL);
  214.     } else {
  215.         /*
  216.          * Case 3: two arbitrary bitmaps.     
  217.          */
  218.         tmode = srcCopy;
  219.         maskPort = TkMacGetDrawablePort(clipPtr->value.pixmap);
  220.         maskBit = &((GrafPtr) maskPort)->portBits;
  221.         CopyDeepMask(srcBit, maskBit, destBit, &srcRect, &srcRect, &destRect, tmode, NULL);
  222.     }
  223.     }
  224.  
  225.     SetGWorld(saveWorld, saveDevice);
  226. }
  227.  
  228. /*
  229.  *----------------------------------------------------------------------
  230.  *
  231.  * TkPutImage --
  232.  *
  233.  *    Copies a subimage from an in-memory image to a rectangle of
  234.  *    of the specified drawable.
  235.  *
  236.  * Results:
  237.  *    None.
  238.  *
  239.  * Side effects:
  240.  *    Draws the image on the specified drawable.
  241.  *
  242.  *----------------------------------------------------------------------
  243.  */
  244.  
  245. void 
  246. TkPutImage(
  247.     unsigned long *colors,    /* Unused on Macintosh. */
  248.     int ncolors,        /* Unused on Macintosh. */
  249.     Display* display,        /* Display. */
  250.     Drawable d,            /* Drawable to place image on. */
  251.     GC gc,            /* GC to use. */
  252.     XImage* image,        /* Image to place. */
  253.     int src_x,            /* Source X & Y. */
  254.     int src_y,
  255.     int dest_x,            /* Destination X & Y. */
  256.     int dest_y,
  257.     unsigned int width,        /* Same width & height for both */
  258.     unsigned int height)    /* distination and source. */
  259. {
  260.     MacDrawable *destDraw = (MacDrawable *) d;
  261.     CGrafPtr saveWorld;
  262.     GDHandle saveDevice;
  263.     GWorldPtr destPort;
  264.     int i, j;
  265.     BitMap bitmap;
  266.     char *newData = NULL;
  267.     Rect destRect, srcRect;
  268.  
  269.     destPort = TkMacGetDrawablePort(d);
  270.     SetRect(&destRect, dest_x, dest_y, dest_x + width, dest_y + height);
  271.     SetRect(&srcRect, src_x, src_y, src_x + width, src_y + height);
  272.  
  273.     display->request++;
  274.     GetGWorld(&saveWorld, &saveDevice);
  275.     SetGWorld(destPort, NULL);
  276.  
  277.     TkMacSetUpClippingRgn(d);
  278.  
  279.     if (image->depth == 1) {
  280.  
  281.     /* 
  282.      * This code assumes a pixel depth of 1 
  283.      */
  284.  
  285.     bitmap.bounds.top = bitmap.bounds.left = 0;
  286.     bitmap.bounds.right = (short) image->width;
  287.     bitmap.bounds.bottom = (short) image->height;
  288.     if ((image->bytes_per_line % 2) == 1) {
  289.         char *newPtr, *oldPtr;
  290.         newData = (char *) ckalloc(image->height *
  291.             (image->bytes_per_line + 1));
  292.         newPtr = newData;
  293.         oldPtr = image->data;
  294.         for (i = 0; i < image->height; i++) {
  295.         for (j = 0; j < image->bytes_per_line; j++) {
  296.             *newPtr = InvertByte((unsigned char) *oldPtr);
  297.             newPtr++, oldPtr++;
  298.         }
  299.         *newPtr = 0;
  300.         newPtr++;
  301.         }
  302.         bitmap.baseAddr = newData;
  303.         bitmap.rowBytes = image->bytes_per_line + 1;
  304.     } else {
  305.         newData = (char *) ckalloc(image->height * image->bytes_per_line);
  306.         for (i = 0; i < image->height * image->bytes_per_line; i++) {
  307.         newData[i] = InvertByte((unsigned char) image->data[i]);
  308.         }        
  309.         bitmap.baseAddr = newData;
  310.         bitmap.rowBytes = image->bytes_per_line;
  311.     }
  312.  
  313.     CopyBits(&bitmap, &((GrafPtr) destPort)->portBits, 
  314.         &srcRect, &destRect, srcCopy, NULL);
  315.  
  316.     } else {
  317.         /* Color image */
  318.         PixMap pixmap;
  319.         
  320.     pixmap.bounds.left = 0;
  321.     pixmap.bounds.top = 0;
  322.     pixmap.bounds.right = (short) image->width;
  323.     pixmap.bounds.bottom = (short) image->height;
  324.     pixmap.pixelType = RGBDirect;
  325.     pixmap.pmVersion = 4;    /* 32bit clean */
  326.     pixmap.packType = 0;
  327.     pixmap.packSize = 0;
  328.     pixmap.hRes = 0x00480000;
  329.     pixmap.vRes = 0x00480000;
  330.     pixmap.pixelSize = 32;
  331.     pixmap.cmpCount = 3;
  332.     pixmap.cmpSize = 8;
  333.     pixmap.planeBytes = 0;
  334.     pixmap.pmTable = NULL;
  335.     pixmap.pmReserved = 0;
  336.     pixmap.baseAddr = image->data;
  337.     pixmap.rowBytes = image->bytes_per_line | 0x8000;
  338.     
  339.     CopyBits((BitMap *) &pixmap, &((GrafPtr) destPort)->portBits, 
  340.         &srcRect, &destRect, srcCopy, NULL);
  341.     }
  342.     
  343.     if (newData != NULL) {
  344.     ckfree(newData);
  345.     }
  346.     SetGWorld(saveWorld, saveDevice);
  347. }
  348.  
  349. /*
  350.  *----------------------------------------------------------------------
  351.  *
  352.  * XFillRectangles --
  353.  *
  354.  *    Fill multiple rectangular areas in the given drawable.
  355.  *
  356.  * Results:
  357.  *    None.
  358.  *
  359.  * Side effects:
  360.  *    Draws onto the specified drawable.
  361.  *
  362.  *----------------------------------------------------------------------
  363.  */
  364.  
  365. void 
  366. XFillRectangles(
  367.     Display* display,        /* Display. */
  368.     Drawable d,            /* Draw on this. */
  369.     GC gc,            /* Use this GC. */
  370.     XRectangle *rectangles,    /* Rectangle array. */
  371.     int n_rectangels)        /* Number of rectangles. */
  372. {
  373.     MacDrawable *macWin = (MacDrawable *) d;
  374.     CGrafPtr saveWorld;
  375.     GDHandle saveDevice;
  376.     GWorldPtr destPort;
  377.     Rect theRect;
  378.     int i;
  379.  
  380.     destPort = TkMacGetDrawablePort(d);
  381.  
  382.     display->request++;
  383.     GetGWorld(&saveWorld, &saveDevice);
  384.     SetGWorld(destPort, NULL);
  385.  
  386.     TkMacSetUpClippingRgn(d);
  387.  
  388.     TkMacSetUpGraphicsPort(gc);
  389.  
  390.     for (i=0; i<n_rectangels; i++) {
  391.     theRect.left = (short) (macWin->xOff + rectangles[i].x);
  392.     theRect.top = (short) (macWin->yOff + rectangles[i].y);
  393.     theRect.right = (short) (theRect.left + rectangles[i].width);
  394.     theRect.bottom = (short) (theRect.top + rectangles[i].height);
  395.     FillCRect(&theRect, gPenPat);
  396.     }
  397.  
  398.     SetGWorld(saveWorld, saveDevice);
  399. }
  400.  
  401. /*
  402.  *----------------------------------------------------------------------
  403.  *
  404.  * XDrawLines --
  405.  *
  406.  *    Draw connected lines.
  407.  *
  408.  * Results:
  409.  *    None.
  410.  *
  411.  * Side effects:
  412.  *    Renders a series of connected lines.
  413.  *
  414.  *----------------------------------------------------------------------
  415.  */
  416.  
  417. void 
  418. XDrawLines(
  419.     Display* display,        /* Display. */
  420.     Drawable d,            /* Draw on this. */
  421.     GC gc,            /* Use this GC. */
  422.     XPoint* points,        /* Array of points. */
  423.     int npoints,        /* Number of points. */
  424.     int mode)            /* Line drawing mode. */
  425. {
  426.     MacDrawable *macWin = (MacDrawable *) d;
  427.     CGrafPtr saveWorld;
  428.     GWorldPtr destPort;
  429.     GDHandle saveDevice;
  430.     int i;
  431.  
  432.     destPort = TkMacGetDrawablePort(d);
  433.  
  434.     display->request++;
  435.     if (npoints < 2) {
  436.         return;  /* TODO: generate BadValue error. */
  437.     }
  438.     GetGWorld(&saveWorld, &saveDevice);
  439.     SetGWorld(destPort, NULL);
  440.     
  441.     TkMacSetUpClippingRgn(d);
  442.  
  443.     TkMacSetUpGraphicsPort(gc);
  444.  
  445.     ShowPen();
  446.  
  447.     PenPixPat(gPenPat);
  448.     MoveTo((short) (macWin->xOff + points[0].x),
  449.         (short) (macWin->yOff + points[0].y));
  450.     for (i = 1; i < npoints; i++) {
  451.     if (mode == CoordModeOrigin) {
  452.         LineTo((short) (macWin->xOff + points[i].x),
  453.             (short) (macWin->yOff + points[i].y));
  454.     } else {
  455.         Line((short) (macWin->xOff + points[i].x),
  456.             (short) (macWin->yOff + points[i].y));
  457.     }
  458.     }
  459.  
  460.     SetGWorld(saveWorld, saveDevice);
  461. }
  462.  
  463. /*
  464.  *----------------------------------------------------------------------
  465.  *
  466.  * XFillPolygon --
  467.  *
  468.  *    Draws a filled polygon.
  469.  *
  470.  * Results:
  471.  *    None.
  472.  *
  473.  * Side effects:
  474.  *    Draws a filled polygon on the specified drawable.
  475.  *
  476.  *----------------------------------------------------------------------
  477.  */
  478.  
  479. void 
  480. XFillPolygon(
  481.     Display* display,        /* Display. */
  482.     Drawable d,            /* Draw on this. */
  483.     GC gc,            /* Use this GC. */
  484.     XPoint* points,        /* Array of points. */
  485.     int npoints,        /* Number of points. */
  486.     int shape,            /* Shape to draw. */
  487.     int mode)            /* Drawing mode. */
  488. {
  489.     MacDrawable *macWin = (MacDrawable *) d;
  490.     PolyHandle polygon;
  491.     CGrafPtr saveWorld;
  492.     GDHandle saveDevice;
  493.     GWorldPtr destPort;
  494.     int i;
  495.  
  496.     destPort = TkMacGetDrawablePort(d);
  497.  
  498.     display->request++;
  499.     GetGWorld(&saveWorld, &saveDevice);
  500.     SetGWorld(destPort, NULL);
  501.  
  502.     TkMacSetUpClippingRgn(d);
  503.     
  504.     TkMacSetUpGraphicsPort(gc);
  505.  
  506.     PenNormal();
  507.     polygon = OpenPoly();
  508.  
  509.     MoveTo((short) (macWin->xOff + points[0].x),
  510.         (short) (macWin->yOff + points[0].y));
  511.     for (i = 1; i < npoints; i++) {
  512.     if (mode == CoordModePrevious) {
  513.         Line((short) (macWin->xOff + points[i].x),
  514.             (short) (macWin->yOff + points[i].y));
  515.     } else {
  516.         LineTo((short) (macWin->xOff + points[i].x),
  517.             (short) (macWin->yOff + points[i].y));
  518.     }
  519.     }
  520.  
  521.     ClosePoly();
  522.  
  523.     FillCPoly(polygon, gPenPat);
  524.  
  525.     KillPoly(polygon);
  526.     SetGWorld(saveWorld, saveDevice);
  527. }
  528.  
  529. /*
  530.  *----------------------------------------------------------------------
  531.  *
  532.  * XDrawRectangle --
  533.  *
  534.  *    Draws a rectangle.
  535.  *
  536.  * Results:
  537.  *    None.
  538.  *
  539.  * Side effects:
  540.  *    Draws a rectangle on the specified drawable.
  541.  *
  542.  *----------------------------------------------------------------------
  543.  */
  544.  
  545. void 
  546. XDrawRectangle(
  547.     Display* display,        /* Display. */
  548.     Drawable d,            /* Draw on this. */
  549.     GC gc,            /* Use this GC. */
  550.     int x,            /* Upper left corner. */
  551.     int y,
  552.     unsigned int width,        /* Width & height of rect. */
  553.     unsigned int height)
  554. {
  555.     MacDrawable *macWin = (MacDrawable *) d;
  556.     Rect theRect;
  557.     CGrafPtr saveWorld;
  558.     GDHandle saveDevice;
  559.     GWorldPtr destPort;
  560.  
  561.     destPort = TkMacGetDrawablePort(d);
  562.  
  563.     display->request++;
  564.     GetGWorld(&saveWorld, &saveDevice);
  565.     SetGWorld(destPort, NULL);
  566.  
  567.     TkMacSetUpClippingRgn(d);
  568.  
  569.     TkMacSetUpGraphicsPort(gc);
  570.  
  571.     theRect.left = (short) (macWin->xOff + x);
  572.     theRect.top = (short) (macWin->yOff + y);
  573.     theRect.right = (short) (theRect.left + width);
  574.     theRect.bottom = (short) (theRect.top + height);
  575.     
  576.     ShowPen();
  577.     PenPixPat(gPenPat);
  578.     FrameRect(&theRect);
  579.  
  580.     SetGWorld(saveWorld, saveDevice);
  581. }
  582.  
  583. /*
  584.  *----------------------------------------------------------------------
  585.  *
  586.  * XDrawArc --
  587.  *
  588.  *    Draw an arc.
  589.  *
  590.  * Results:
  591.  *    None.
  592.  *
  593.  * Side effects:
  594.  *    Draws an arc on the specified drawable.
  595.  *
  596.  *----------------------------------------------------------------------
  597.  */
  598.  
  599. void 
  600. XDrawArc(
  601.     Display* display,        /* Display. */
  602.     Drawable d,            /* Draw on this. */
  603.     GC gc,            /* Use this GC. */
  604.     int x,            /* Upper left of */
  605.     int y,            /* bounding rect. */
  606.     unsigned int width,        /* Width & height. */
  607.     unsigned int height,
  608.     int angle1,            /* Staring angle of arc. */
  609.     int angle2)            /* Ending angle of arc. */
  610. {
  611.     MacDrawable *macWin = (MacDrawable *) d;
  612.     Rect theRect;
  613.     short start, extent;
  614.     CGrafPtr saveWorld;
  615.     GDHandle saveDevice;
  616.     GWorldPtr destPort;
  617.  
  618.     destPort = TkMacGetDrawablePort(d);
  619.  
  620.     display->request++;
  621.     GetGWorld(&saveWorld, &saveDevice);
  622.     SetGWorld(destPort, NULL);
  623.  
  624.     TkMacSetUpClippingRgn(d);
  625.  
  626.     TkMacSetUpGraphicsPort(gc);
  627.  
  628.     theRect.left = (short) (macWin->xOff + x);
  629.     theRect.top = (short) (macWin->yOff + y);
  630.     theRect.right = (short) (theRect.left + width);
  631.     theRect.bottom = (short) (theRect.top + height);
  632.     start = (short) (90 - (angle1 / 64));
  633.     extent = (short) (-(angle2 / 64));
  634.  
  635.     ShowPen();
  636.     PenPixPat(gPenPat);
  637.     FrameArc(&theRect, start, extent);
  638.  
  639.     SetGWorld(saveWorld, saveDevice);
  640. }
  641.  
  642. /*
  643.  *----------------------------------------------------------------------
  644.  *
  645.  * XFillArc --
  646.  *
  647.  *    Draw a filled arc.
  648.  *
  649.  * Results:
  650.  *    None.
  651.  *
  652.  * Side effects:
  653.  *    Draws a filled arc on the specified drawable.
  654.  *
  655.  *----------------------------------------------------------------------
  656.  */
  657.  
  658. void
  659. XFillArc(
  660.     Display* display,        /* Display. */
  661.     Drawable d,            /* Draw on this. */
  662.     GC gc,            /* Use this GC. */
  663.     int x,            /* Upper left of */
  664.     int y,            /* bounding rect. */
  665.     unsigned int width,        /* Width & height. */
  666.     unsigned int height,
  667.     int angle1,            /* Staring angle of arc. */
  668.     int angle2)            /* Ending angle of arc. */
  669. {
  670.     MacDrawable *macWin = (MacDrawable *) d;
  671.     Rect theRect;
  672.     short start, extent;
  673.     PolyHandle polygon;
  674.     double sin1, cos1, sin2, cos2, angle;
  675.     double boxWidth, boxHeight;
  676.     double vertex[2], center1[2], center2[2];
  677.     CGrafPtr saveWorld;
  678.     GDHandle saveDevice;
  679.     GWorldPtr destPort;
  680.  
  681.     destPort = TkMacGetDrawablePort(d);
  682.  
  683.     display->request++;
  684.     GetGWorld(&saveWorld, &saveDevice);
  685.     SetGWorld(destPort, NULL);
  686.  
  687.     TkMacSetUpClippingRgn(d);
  688.  
  689.     TkMacSetUpGraphicsPort(gc);
  690.  
  691.     theRect.left = (short) (macWin->xOff + x);
  692.     theRect.top = (short) (macWin->yOff + y);
  693.     theRect.right = (short) (theRect.left + width);
  694.     theRect.bottom = (short) (theRect.top + height);
  695.     start = (short) (90 - (angle1 / 64));
  696.     extent = (short) (- (angle2 / 64));
  697.  
  698.     if (gc->arc_mode == ArcChord) {
  699.         boxWidth = theRect.right - theRect.left;
  700.         boxHeight = theRect.bottom - theRect.top;
  701.         angle = -(angle1/64.0)*PI/180.0;
  702.         sin1 = sin(angle);
  703.         cos1 = cos(angle);
  704.         angle -= (angle2/64.0)*PI/180.0;
  705.         sin2 = sin(angle);
  706.         cos2 = cos(angle);
  707.         vertex[0] = (theRect.left + theRect.right)/2.0;
  708.         vertex[1] = (theRect.top + theRect.bottom)/2.0;
  709.         center1[0] = vertex[0] + cos1*boxWidth/2.0;
  710.         center1[1] = vertex[1] + sin1*boxHeight/2.0;
  711.         center2[0] = vertex[0] + cos2*boxWidth/2.0;
  712.         center2[1] = vertex[1] + sin2*boxHeight/2.0;
  713.  
  714.     polygon = OpenPoly();
  715.     MoveTo((short) ((theRect.left + theRect.right)/2),
  716.         (short) ((theRect.top + theRect.bottom)/2));
  717.     
  718.     LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5));
  719.     LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5));
  720.     ClosePoly();
  721.  
  722.     ShowPen();
  723.     FillCArc(&theRect, start, extent, gPenPat);
  724.     FillCPoly(polygon, gPenPat);
  725.  
  726.     KillPoly(polygon);
  727.     } else {
  728.     ShowPen();
  729.     FillCArc(&theRect, start, extent, gPenPat);
  730.     }
  731.  
  732.     SetGWorld(saveWorld, saveDevice);
  733. }
  734.  
  735. /*
  736.  *----------------------------------------------------------------------
  737.  *
  738.  * TkScrollWindow --
  739.  *
  740.  *    Scroll a rectangle of the specified window and accumulate
  741.  *    a damage region.
  742.  *
  743.  * Results:
  744.  *    Returns 0 if the scroll genereated no additional damage.
  745.  *    Otherwise, sets the region that needs to be repainted after
  746.  *    scrolling and returns 1.
  747.  *
  748.  * Side effects:
  749.  *    Scrolls the bits in the window.
  750.  *
  751.  *----------------------------------------------------------------------
  752.  */
  753.  
  754. int
  755. TkScrollWindow(
  756.     Tk_Window tkwin,        /* The window to be scrolled. */
  757.     GC gc,            /* GC for window to be scrolled. */
  758.     int x,            /* Position rectangle to be scrolled. */
  759.     int y,
  760.     int width,
  761.     int height,
  762.     int dx,            /* Distance rectangle should be moved. */
  763.     int dy,
  764.     TkRegion damageRgn)        /* Region to accumulate damage in. */
  765. {
  766.     MacDrawable *destDraw = (MacDrawable *) Tk_WindowId(tkwin);
  767.     RgnHandle rgn = (RgnHandle) damageRgn;
  768.     CGrafPtr saveWorld;
  769.     GDHandle saveDevice;
  770.     GWorldPtr destPort;
  771.     Rect srcRect, scrollRect;
  772.     
  773.     destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
  774.  
  775.     GetGWorld(&saveWorld, &saveDevice);
  776.     SetGWorld(destPort, NULL);
  777.  
  778.     TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
  779.  
  780.     /*
  781.      * Due to the implementation below the behavior may be differnt
  782.      * than X in certain cases that should never occur in Tk.  The 
  783.      * scrollRect is the source rect extended by the offset (the union 
  784.      * of the source rect and the offset rect).  Everything
  785.      * in the extended scrollRect is scrolled.  On X, it's possible
  786.      * to "skip" over an area if the offset makes the source and
  787.      * destination rects disjoint and non-aligned.
  788.      */
  789.        
  790.     SetRect(&srcRect, (short) (destDraw->xOff + x),
  791.         (short) (destDraw->yOff + y),
  792.         (short) (destDraw->xOff + x + width),
  793.         (short) (destDraw->yOff + y + height));
  794.     scrollRect = srcRect;
  795.     if (dx < 0) {
  796.     scrollRect.left += dx;
  797.     } else {
  798.     scrollRect.right += dx;
  799.     }
  800.     if (dy < 0) {
  801.     scrollRect.top += dy;
  802.     } else {
  803.     scrollRect.bottom += dy;
  804.     }
  805.  
  806.     /*
  807.      * Adjust clip region so that we don't copy any windows
  808.      * that may overlap us.
  809.      */
  810.     RectRgn(rgn, &srcRect);
  811.     DiffRgn(rgn, destPort->visRgn, rgn);
  812.     OffsetRgn(rgn, dx, dy);
  813.     DiffRgn(destPort->clipRgn, rgn, destPort->clipRgn);
  814.     SetEmptyRgn(rgn);
  815.     
  816.     /*
  817.      * When a menu is up, the Mac does not expect drawing to occur and
  818.      * does not clip out the menu. We have to do it ourselves. This
  819.      * is pretty gross.
  820.      */
  821.  
  822.     if (tkUseMenuCascadeRgn == 1) {
  823.         Point scratch = {0, 0};
  824.         MacDrawable *macDraw = (MacDrawable *) Tk_WindowId(tkwin);
  825.  
  826.     LocalToGlobal(&scratch);
  827.     CopyRgn(tkMenuCascadeRgn, rgn);
  828.     OffsetRgn(rgn, -scratch.h, -scratch.v);
  829.     DiffRgn(destPort->clipRgn, rgn, destPort->clipRgn);
  830.     SetEmptyRgn(rgn);
  831.     macDraw->toplevel->flags |= TK_DRAWN_UNDER_MENU;
  832.     }
  833.     
  834.     ScrollRect(&scrollRect, dx, dy, rgn);
  835.     
  836.     SetGWorld(saveWorld, saveDevice);
  837.     
  838.     /*
  839.      * Fortunantly, the region returned by ScrollRect is symanticlly
  840.      * the same as what we need to return in this function.  If the
  841.      * region is empty we return zero to denote that no damage was
  842.      * created.
  843.      */
  844.     if (EmptyRgn(rgn)) {
  845.     return 0;
  846.     } else {
  847.     return 1;
  848.     }
  849. }
  850.  
  851. /*
  852.  *----------------------------------------------------------------------
  853.  *
  854.  * TkMacSetUpGraphicsPort --
  855.  *
  856.  *    Set up the graphics port from the given GC.
  857.  *
  858.  * Results:
  859.  *    None.
  860.  *
  861.  * Side effects:
  862.  *    The current port is adjusted.
  863.  *
  864.  *----------------------------------------------------------------------
  865.  */
  866.  
  867. void
  868. TkMacSetUpGraphicsPort(
  869.     GC gc)        /* GC to apply to current port. */
  870. {
  871.     RGBColor macColor;
  872.  
  873.     if (gPenPat == NULL) {
  874.     gPenPat = NewPixPat();
  875.     }
  876.     
  877.     if (TkSetMacColor(gc->foreground, &macColor) == true) {
  878.         /* TODO: cache RGBPats for preformace - measure gains...  */
  879.     MakeRGBPat(gPenPat, &macColor);
  880.     }
  881.     
  882.     PenNormal();
  883.     if(gc->function == GXxor) {
  884.     PenMode(patXor);
  885.     }
  886.     if (gc->line_width > 1) {
  887.     PenSize(gc->line_width, gc->line_width);
  888.     }
  889. }
  890.  
  891. /*
  892.  *----------------------------------------------------------------------
  893.  *
  894.  * TkMacSetUpClippingRgn --
  895.  *
  896.  *    Set up the clipping region so that drawing only occurs on the
  897.  *    specified X subwindow.
  898.  *
  899.  * Results:
  900.  *    None.
  901.  *
  902.  * Side effects:
  903.  *    The clipping region in the current port is changed.
  904.  *
  905.  *----------------------------------------------------------------------
  906.  */
  907.  
  908. void
  909. TkMacSetUpClippingRgn(
  910.     Drawable drawable)        /* Drawable to update. */
  911. {
  912.     MacDrawable *macDraw = (MacDrawable *) drawable;
  913.  
  914.     if (macDraw->winPtr != NULL) {
  915.     if (macDraw->flags & TK_CLIP_INVALID) {
  916.         TkMacUpdateClipRgn(macDraw->winPtr);
  917.     }
  918.  
  919.     /*
  920.      * When a menu is up, the Mac does not expect drawing to occur and
  921.      * does not clip out the menu. We have to do it ourselves. This
  922.      * is pretty gross.
  923.      */
  924.  
  925.     if (macDraw->clipRgn != NULL) {
  926.         if (tkUseMenuCascadeRgn == 1) {
  927.             Point scratch = {0, 0};
  928.             GDHandle saveDevice;
  929.             GWorldPtr saveWorld;
  930.             
  931.             GetGWorld(&saveWorld, &saveDevice);
  932.             SetGWorld(TkMacGetDrawablePort(drawable), NULL);
  933.             LocalToGlobal(&scratch);
  934.             SetGWorld(saveWorld, saveDevice);
  935.             if (tmpRgn == NULL) {
  936.                 tmpRgn = NewRgn();
  937.             }
  938.             CopyRgn(tkMenuCascadeRgn, tmpRgn);
  939.             OffsetRgn(tmpRgn, -scratch.h, -scratch.v);
  940.             DiffRgn(macDraw->clipRgn, tmpRgn, tmpRgn);
  941.             SetClip(tmpRgn);
  942.             macDraw->toplevel->flags |= TK_DRAWN_UNDER_MENU;
  943.         } else {
  944.             SetClip(macDraw->clipRgn);
  945.         }
  946.     }
  947.     }
  948. }
  949.  
  950. /*
  951.  *----------------------------------------------------------------------
  952.  *
  953.  * TkMacMakeStippleMap --
  954.  *
  955.  *    Given a drawable and a stipple pattern this function draws the
  956.  *    pattern repeatedly over the drawable.  The drawable can then
  957.  *    be used as a mask for bit-bliting a stipple pattern over an
  958.  *    object.
  959.  *
  960.  * Results:
  961.  *    A BitMap data structure.
  962.  *
  963.  * Side effects:
  964.  *    None.
  965.  *
  966.  *----------------------------------------------------------------------
  967.  */
  968.  
  969. BitMapPtr
  970. TkMacMakeStippleMap(
  971.     Drawable drawable,        /* Window to apply stipple. */
  972.     Drawable stipple)        /* The stipple pattern. */
  973. {
  974.     MacDrawable *destDraw = (MacDrawable *) drawable;
  975.     GWorldPtr destPort;
  976.     BitMapPtr bitmapPtr;
  977.     int width, height, stippleHeight, stippleWidth;
  978.     int i, j;
  979.     char * data;
  980.     Rect bounds;
  981.  
  982.     destPort = TkMacGetDrawablePort(drawable);
  983.     width = destPort->portRect.right - destPort->portRect.left;
  984.     height = destPort->portRect.bottom - destPort->portRect.top;
  985.     
  986.     bitmapPtr = (BitMap *) ckalloc(sizeof(BitMap));
  987.     data = (char *) ckalloc(height * ((width / 8) + 1));
  988.     bitmapPtr->bounds.top = bitmapPtr->bounds.left = 0;
  989.     bitmapPtr->bounds.right = (short) width;
  990.     bitmapPtr->bounds.bottom = (short) height;
  991.     bitmapPtr->baseAddr = data;
  992.     bitmapPtr->rowBytes = (width / 8) + 1;
  993.  
  994.     destPort = TkMacGetDrawablePort(stipple);
  995.     stippleWidth = destPort->portRect.right - destPort->portRect.left;
  996.     stippleHeight = destPort->portRect.bottom - destPort->portRect.top;
  997.  
  998.     for (i = 0; i < height; i += stippleHeight) {
  999.     for (j = 0; j < width; j += stippleWidth) {
  1000.         bounds.left = j;
  1001.         bounds.top = i;
  1002.         bounds.right = j + stippleWidth;
  1003.         bounds.bottom = i + stippleHeight;
  1004.         
  1005.         CopyBits(&((GrafPtr) destPort)->portBits, bitmapPtr, 
  1006.         &((GrafPtr) destPort)->portRect, &bounds, srcCopy, NULL);
  1007.     }
  1008.     }
  1009.     return bitmapPtr;
  1010. }
  1011.  
  1012. /*
  1013.  *----------------------------------------------------------------------
  1014.  *
  1015.  * InvertByte --
  1016.  *
  1017.  *      This function reverses the bits in the passed in Byte of data.
  1018.  *
  1019.  * Results:
  1020.  *      The incoming byte in reverse bit order.
  1021.  *
  1022.  * Side effects:
  1023.  *      None.
  1024.  *
  1025.  *----------------------------------------------------------------------
  1026.  */
  1027.  
  1028. static unsigned char
  1029. InvertByte(
  1030.     unsigned char data)        /* Byte of data. */
  1031. {
  1032.     unsigned char i;
  1033.     unsigned char mask = 1, result = 0;
  1034.  
  1035.     for (i = (1 << 7); i != 0; i /= 2) {
  1036.         if (data & mask) {
  1037.             result |= i;
  1038.         }
  1039.         mask = mask << 1;
  1040.     }
  1041.     return result;
  1042. }
  1043.