home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xpaint-244 / src / sprayop.c < prev    next >
C/C++ Source or Header  |  1996-05-09  |  8KB  |  339 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* | Copyright 1995, 1996 Torsten Martinsen (bullestock@dk-online.dk)  | */
  4. /* |                                                                   | */
  5. /* | Permission to use, copy, modify, and to distribute this software  | */
  6. /* | and its documentation for any purpose is hereby granted without   | */
  7. /* | fee, provided that the above copyright notice appear in all       | */
  8. /* | copies and that both that copyright notice and this permission    | */
  9. /* | notice appear in supporting documentation.  There is no           | */
  10. /* | representations about the suitability of this software for        | */
  11. /* | any purpose.  this software is provided "as is" without express   | */
  12. /* | or implied warranty.                                              | */
  13. /* |                                                                   | */
  14. /* +-------------------------------------------------------------------+ */
  15.  
  16. /* $Id: sprayOp.c,v 1.5 1996/05/09 07:11:38 torsten Exp $ */
  17.  
  18. #include <X11/Intrinsic.h>
  19. #include <X11/StringDefs.h>
  20. #include <X11/cursorfont.h>
  21. #include <X11/Xos.h>
  22. #include <sys/time.h>
  23. #include <math.h>
  24.  
  25. #include "xpaint.h"
  26. #include "Paint.h"
  27. #include "misc.h"
  28. #include "ops.h"
  29.  
  30. #ifndef NOSTDHDRS
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #endif
  34.  
  35. typedef struct {
  36.     Widget w;
  37.     int useGauss;
  38.     int x, y;
  39.     XtIntervalId id;
  40.     Boolean gcFlag, isTiled, trackDrawn, drawing;
  41.     int lastX, lastY;
  42.     int zoom;
  43.     /*
  44.     **  Borrowed from the info
  45.      */
  46.     GC gc, gcx;
  47.     Pixmap drawable;
  48.     Boolean isFat;
  49. } LocalInfo;
  50.  
  51. static int radius = 10, density = 10, radius2 = 10 * 10, rate = 100;
  52. static Boolean style = True;
  53.  
  54.  
  55. static void 
  56. draw(LocalInfo * l)
  57. {
  58.     int i;
  59.     XRectangle rect;
  60.     union {
  61.     XSegment s[512];
  62.     XPoint p[512];
  63.     } p;
  64.  
  65.     UndoGrow(l->w, l->x - radius, l->y - radius);
  66.     UndoGrow(l->w, l->x + radius, l->y + radius);
  67.  
  68.     for (i = 0; i < density; i++) {
  69.     int rx, ry;
  70.  
  71.     do {
  72.         if (l->useGauss) {
  73.         rx = gaussclamp(radius);
  74.         ry = gaussclamp(radius);
  75.         } else {
  76.         rx = RANDOMI2(-radius, radius);
  77.         ry = RANDOMI2(-radius, radius);
  78.         }
  79.     }
  80.     while (rx * rx + ry * ry > radius2);
  81.  
  82.     if (l->isTiled) {
  83.         p.s[i].x1 = l->x + rx;
  84.         p.s[i].y1 = l->y + ry;
  85.         p.s[i].x2 = l->x + rx;
  86.         p.s[i].y2 = l->y + ry;
  87.     } else {
  88.         p.p[i].x = l->x + rx;
  89.         p.p[i].y = l->y + ry;
  90.     }
  91.     }
  92.  
  93.     XYtoRECT(l->x - radius, l->y - radius,
  94.          l->x + radius, l->y + radius, &rect);
  95.  
  96.     if (l->isTiled) {
  97.     XDrawSegments(XtDisplay(l->w), l->drawable, l->gc, p.s, density);
  98.     if (!l->isFat)
  99.         XDrawSegments(XtDisplay(l->w), XtWindow(l->w), l->gc, p.s, density);
  100.     } else {
  101.     XDrawPoints(XtDisplay(l->w), l->drawable, l->gc, p.p, density, CoordModeOrigin);
  102.     if (!l->isFat)
  103.         XDrawPoints(XtDisplay(l->w), XtWindow(l->w), l->gc,
  104.             p.p, density, CoordModeOrigin);
  105.     }
  106.  
  107.     PwUpdate(l->w, &rect, False);
  108. }
  109.  
  110. static void 
  111. drawEvent(LocalInfo * l)
  112. {
  113.     draw(l);
  114.     l->id = XtAppAddTimeOut(XtWidgetToApplicationContext(l->w),
  115.            rate, (XtTimerCallbackProc) drawEvent, (XtPointer) l);
  116. }
  117.  
  118. static void 
  119. drawOutline(Widget w, LocalInfo * l, int x, int y, Boolean flag)
  120. {
  121.     Display *dpy = XtDisplay(w);
  122.     Window window = XtWindow(w);
  123.     XArc arc;
  124.  
  125.     arc.width = radius * l->zoom * 2;
  126.     arc.height = radius * l->zoom * 2;
  127.     arc.angle1 = 0;
  128.     arc.angle2 = 360 * 64;
  129.  
  130.     if (l->trackDrawn) {
  131.     arc.x = l->lastX - radius * l->zoom;
  132.     arc.y = l->lastY - radius * l->zoom;
  133.     XDrawArcs(dpy, window, l->gcx, &arc, 1);
  134.     l->trackDrawn = False;
  135.     }
  136.     if (flag) {
  137.     arc.x = x - radius * l->zoom;
  138.     arc.y = y - radius * l->zoom;
  139.     XDrawArcs(dpy, window, l->gcx, &arc, 1);
  140.  
  141.     l->lastX = x;
  142.     l->lastY = y;
  143.     l->trackDrawn = True;
  144.     }
  145. }
  146.  
  147.  
  148. static void 
  149. press(Widget w, LocalInfo * l, XButtonEvent * event, OpInfo * info)
  150. {
  151.     GC sgc;
  152.     int width, rule, rule2;
  153.  
  154.     /*
  155.     **  Check to make sure all buttons are up, before doing this
  156.      */
  157.     if ((event->state & AllButtonsMask) != 0)
  158.     return;
  159.  
  160.     l->x = event->x;
  161.     l->y = event->y;
  162.  
  163.     l->useGauss = style;
  164.     l->drawing = True;
  165.     drawOutline(w, l, 0, 0, False);
  166.  
  167.     UndoStartPoint(w, info, event->x, event->y);
  168.  
  169.     l->drawable = info->drawable;
  170.     l->isFat = info->isFat;
  171.  
  172.     XtVaGetValues(w, XtNlineWidth, &width,
  173.           XtNfillRule, &rule,
  174.           XtNlineFillRule, &rule2,
  175.           NULL);
  176.     if (!l->gcFlag)
  177.     l->gcFlag = (width != 0);
  178.  
  179.     if (event->button == Button2) {
  180.     sgc = info->second_gc;
  181.     l->isTiled = (rule2 != FillSolid);
  182.     } else if (event->button == Button1) {
  183.     sgc = info->first_gc;
  184.     l->isTiled = (rule != FillSolid);
  185.     } else
  186.     return;
  187.  
  188.     if (l->gcFlag) {
  189.     if (l->gc == None)
  190.         l->gc = XCreateGC(XtDisplay(w), info->drawable, 0, NULL);
  191.     XCopyGC(XtDisplay(w), sgc, ~GCLineWidth, l->gc);
  192.     } else {
  193.     l->gc = sgc;
  194.     }
  195.  
  196.     if (l->id == (XtIntervalId) NULL)
  197.     drawEvent(l);
  198.     else
  199.     draw(l);
  200. }
  201.  
  202. static void 
  203. motion(Widget w, LocalInfo * l, XMotionEvent * event, OpInfo * info)
  204. {
  205.     if (l->drawing && info->surface == opPixmap) {
  206.     l->x = event->x;
  207.     l->y = event->y;
  208.  
  209.     draw(l);
  210.     } else if (!l->drawing && info->surface == opWindow) {
  211.     l->zoom = info->zoom;
  212.     drawOutline(w, l, event->x, event->y, True);
  213.     }
  214. }
  215.  
  216. static void 
  217. release(Widget w, LocalInfo * l, XButtonEvent * event, OpInfo * info)
  218. {
  219.     int mask;
  220.  
  221.     /*
  222.     **  Check to make sure all buttons are up, before doing this
  223.      */
  224.     mask = AllButtonsMask;
  225.     switch (event->button) {
  226.     case Button1:
  227.     mask ^= Button1Mask;
  228.     break;
  229.     case Button2:
  230.     mask ^= Button2Mask;
  231.     break;
  232.     case Button3:
  233.     mask ^= Button3Mask;
  234.     break;
  235.     case Button4:
  236.     mask ^= Button4Mask;
  237.     break;
  238.     case Button5:
  239.     mask ^= Button5Mask;
  240.     break;
  241.     }
  242.     if ((event->state & mask) != 0)
  243.     return;
  244.  
  245.     if (l->id != (XtIntervalId) NULL)
  246.     XtRemoveTimeOut(l->id);
  247.  
  248.     l->id = (XtIntervalId) NULL;
  249.     l->drawing = False;
  250. }
  251.  
  252. static void 
  253. leave(Widget w, LocalInfo * l, XEvent * event, OpInfo * info)
  254. {
  255.     drawOutline(w, l, 0, 0, False);
  256. }
  257.  
  258.  
  259. /*
  260. **  Those public functions
  261.  */
  262. void 
  263. SpraySetParameters(int r, int d, int sp)
  264. {
  265.     radius = r;
  266.     radius2 = r * r;
  267.     density = d;
  268.     rate = sp * 10;
  269. }
  270.  
  271. Boolean
  272. SprayGetStyle(void)
  273. {
  274.     return style;
  275. }
  276.  
  277. void 
  278. SpraySetStyle(Boolean flag)
  279. {
  280.     style = flag;
  281. }
  282.  
  283. static void *
  284. commonSprayAdd(Widget w, Boolean flag)
  285. {
  286.     LocalInfo *l = XtNew(LocalInfo);
  287.  
  288.     l->w = w;
  289.     l->id = (XtIntervalId) NULL;
  290.     l->gc = None;
  291.     l->gcx = GetGCX(w);
  292.     l->gcFlag = False;
  293.     l->useGauss = flag;
  294.     l->trackDrawn = False;
  295.     l->drawing = False;
  296.  
  297.     XtVaSetValues(w, XtNcompress, False,
  298.     XtVaTypedArg, XtNcursor, XtRString, "spraycan", sizeof(Cursor), NULL);
  299.  
  300.     OpAddEventHandler(w, opPixmap, ButtonPressMask, FALSE,
  301.               (OpEventProc) press, l);
  302.     OpAddEventHandler(w, opWindow | opPixmap, PointerMotionMask, FALSE,
  303.               (OpEventProc) motion, l);
  304.     OpAddEventHandler(w, opPixmap, ButtonReleaseMask, FALSE,
  305.               (OpEventProc) release, l);
  306.     OpAddEventHandler(w, opWindow, LeaveWindowMask, FALSE,
  307.               (OpEventProc) leave, l);
  308.  
  309.     return l;
  310. }
  311.  
  312. void *
  313. SprayAdd(Widget w)
  314. {
  315.     return commonSprayAdd(w, style);
  316. }
  317.  
  318. void 
  319. SprayRemove(Widget w, void *p)
  320. {
  321.     LocalInfo *l = (LocalInfo *) p;
  322.  
  323.     OpRemoveEventHandler(w, opPixmap, ButtonPressMask, FALSE,
  324.              (OpEventProc) press, l);
  325.     OpRemoveEventHandler(w, opWindow | opPixmap, PointerMotionMask, FALSE,
  326.              (OpEventProc) motion, l);
  327.     OpRemoveEventHandler(w, opPixmap, ButtonReleaseMask, FALSE,
  328.              (OpEventProc) release, l);
  329.     OpRemoveEventHandler(w, opWindow, LeaveWindowMask, FALSE,
  330.              (OpEventProc) leave, l);
  331.  
  332.     if (l->gcFlag)
  333.     XFreeGC(XtDisplay(w), l->gc);
  334.     if (l->id != (XtIntervalId) NULL)
  335.     XtRemoveTimeOut(l->id);
  336.  
  337.     XtFree((XtPointer) l);
  338. }
  339.