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

通讯编程

开发平台:

Visual C++

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