naughton@wind.Eng.Sun.COM (Patrick Naughton) (02/17/91)
In article <85040@sgi.sgi.com>, paul@manray.asd.sgi.com (Paul Haeberli) writes: |> Here's a little program that uses a very simple dynamics model |> to draw caligraphic strokes. Please give it a try if you have |> an IRIS workstation. |> |> paul haeberli |> paul@sgi.com |> 415-962-3665 |> |> ... dynadraw.c deleted ... Here's another set of X11 compatibility routines for us Paul Haeberli fans without IRISes... compile it like this: cc -O dynadraw.c glx.c -o dynadraw -lm -lX #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # glx.c # gl.h # device.h # This archive created: Sat Feb 16 23:30:16 1991 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'glx.c' then echo shar: "will not over-write existing file 'glx.c'" else cat << \SHAR_EOF > 'glx.c' #ident "@(#)glx.c 1.1 91/02/16 GL" /*- * glx.c - simple replacements for SGI GL functions for X11. * * Copyright (c) 1991 by Patrick J. Naughton * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * * Comments and additions should be sent to the author: * * Patrick J. Naughton * Sun Microsystems * 2550 Garcia Ave, MS 10-20 * Mountain View, CA 94043 * (415) 336-1080 * */ #include <stdio.h> #include <sys/times.h> #include <string.h> #include <strings.h> #include <X11/Xlib.h> #include <X11/Xatom.h> #include <X11/Xutil.h> #include <X11/keysym.h> #include <X11/bitmaps/gray1> #include "gl.h" #define POLYBATCH 40 #define FONTNAME "bembo-bold-24" static Display *dsp; static int screen; static Colormap cmap; static GC gc; static Window win; static Window root; static int winw; static int winh; static int cpx; static int cpy; static XPoint *poly = 0; static int curpoly; static int npoly; static XFontStruct *textfont; static XFontStruct *font; static XCharStruct fontextent; static int fontascent; static int fontdescent; static int fontheight; static int menux; static int menuy; static long black; static long white; static float xoff; static float xscale; static float yoff; static float yscale; static Pixmap stipple; static int mousex; static int mousey; void prefsize(w, h) { winw = w; winh = h; } void winopen(name) char *name; { XSetWindowAttributes xswa; XWMHints xwmh; int tmp; int mask; dsp = XOpenDisplay(0); screen = DefaultScreen(dsp); cmap = DefaultColormap(dsp, screen); gc = DefaultGC(dsp, screen); root = RootWindow(dsp, screen); black = BlackPixel(dsp, screen); white = WhitePixel(dsp, screen); stipple = XCreatePixmapFromBitmapData(dsp, root, gray1_bits, gray1_width, gray1_height, black, white, 1); XSetStipple(dsp, gc, stipple); font = XLoadQueryFont(dsp, "fixed"); textfont = XLoadQueryFont(dsp, FONTNAME); if (!textfont) textfont = font; XSetFont(dsp, gc, textfont->fid); XQueryTextExtents(dsp, textfont->fid, "Q", 1, &tmp, &fontascent, &fontdescent, &fontextent); fontheight = fontascent + fontdescent + 1; xswa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | Button2MotionMask; mask = CWEventMask; win = XCreateWindow(dsp, root, 0, 0, winw, winh, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &xswa); xwmh.flags = InputHint; xwmh.input = True; XChangeProperty(dsp, win, XA_WM_HINTS, XA_WM_HINTS, 32, PropModeReplace, (unsigned char *) &xwmh, sizeof(xwmh) / sizeof(int)); XStoreName(dsp, win, name); XMapWindow(dsp, win); while (1) { XEvent ev; XNextEvent(dsp, &ev); if (ev.type == Expose) break; } } /* this is a hack to make Sun's times return the time value just like SYSV */ #undef times long mytimes(ct) struct tms *ct; { times(ct); return ct->tms_utime; } void RGBcolor(r, g, b) { XColor color; color.pixel = 0; color.red = r << 8; color.green = g << 8; color.blue = b << 8; color.flags = DoRed | DoGreen | DoBlue; XAllocColor(dsp, cmap, &color); XSetForeground(dsp, gc, color.pixel); } void clear() { XFillRectangle(dsp, win, gc, 0, 0, winw, winh); } void pnt2i(x, y) int x; int y; { XDrawPoint(dsp, win, gc, x, winh - y); } int getvaluator(which) int which; { switch (which) { case MOUSEX: return mousex; case MOUSEY: return winh - mousey; default: return 0; } } int getbutton(which) int which; { Window qroot; Window qwin; int rootx; int rooty; int winx; int winy; static int mask; XQueryPointer(dsp, win, &qroot, &qwin, &rootx, &rooty, &winx, &winy, &mask); switch (which) { case LEFTMOUSE: mousex = winx; mousey = winy; return (mask & Button1Mask); case RIGHTSHIFTKEY: return (mask & ShiftMask); default: return 0; } } int qread(val) short *val; { XEvent ev; *val = 1; XNextEvent(dsp, &ev); switch (ev.type) { case Expose: if (((XExposeEvent *) & ev)->window == win) return REDRAW; break; case KeyPress: { XKeyEvent *xke = (XKeyEvent *) & ev; KeySym keysym = XLookupKeysym(xke, 0); switch (keysym) { case XK_Up: return UPARROWKEY; case XK_Down: return DOWNARROWKEY; default: break; } } break; case ButtonPress: { XButtonEvent *xbe = (XButtonEvent *) & ev; switch (xbe->button) { case Button1: mousex = xbe->x; mousey = xbe->y; return LEFTMOUSE; case Button2: return MIDDLEMOUSE; case Button3: menux = xbe->x_root; menuy = xbe->y_root; return MENUBUTTON; default: break; } } break; case MotionNotify: break; } } void getorigin(xo, yo) int *xo; int *yo; { *xo = 0; *yo = 0; } void getsize(xs, ys) int *xs; int *ys; { *xs = winw; *ys = winh; } void move2i(x, y) int x, y; { cpx = x; cpy = y; } /* NB: what's the difference between cmov2i and move2i??? */ void cmov2i(x, y) int x, y; { cpx = x; cpy = y; } void draw2i(x, y) int x, y; { XDrawLine(dsp, win, gc, cpx, winh - cpy, x, winh - y); cpx = x; cpy = y; } void rectfi(x1, y1, x2, y2) int x1; int y1; int x2; int y2; { XFillRectangle(dsp, win, gc, x1, winh - y2, x2 - x1, y2 - y1); } void charstr(str) char *str; { XSetFont(dsp, gc, font->fid); XDrawString(dsp, win, gc, cpx, winh - cpy, str, strlen(str)); XSetFont(dsp, gc, textfont->fid); } void sginap(len) int len; { usleep(len); } void bgnpolygon() { if (poly == 0) { poly = (XPoint *) malloc(POLYBATCH * sizeof(XPoint)); npoly = POLYBATCH; } curpoly = 0; } static void addpoint(x, y) int x; int y; { if (curpoly >= npoly) { npoly += POLYBATCH; poly = (XPoint *) realloc(poly, npoly * sizeof(XPoint)); } poly[curpoly].x = x; poly[curpoly].y = y; curpoly++; } void v2f(p) float *p; { addpoint((int) ((xoff + p[0]) * xscale), winh - (int) ((yoff + p[1]) * yscale)); } void endpolygon() { XFillPolygon(dsp, win, gc, poly, curpoly, Nonconvex, CoordModeOrigin); } void bgnclosedline() { if (poly == 0) { poly = (XPoint *) malloc(POLYBATCH * sizeof(XPoint)); npoly = POLYBATCH; } curpoly = 0; } void endclosedline() { addpoint(poly[0].x, poly[0].y); XDrawLines(dsp, win, gc, poly, curpoly, CoordModeOrigin); } void ortho2(xmin, xmax, ymin, ymax) float xmin; float xmax; float ymin; float ymax; { xoff = xmin; xscale = winw / (xmax - xmin); yoff = ymin; yscale = winh / (ymax - ymin); } /* * these routines are a cheesy ten minute hack to do menus with GL's API. */ #define MAXMENUS 10 #define MAXMENUITEMS 10 typedef struct { char *title; int titlewidth; int nitems; char *item[MAXMENUITEMS]; Window win; int w; int h; } MenuStruct; MenuStruct menu[10]; int nummenus = 0; #define MENUPADW 20 #define MENUPADH 4 #define MENUPADTITLE 8 #define SHADE 16 int defpup(s) char *s; { int n = nummenus++; char *val = strtok(s, "|"); int w; int mask; int maxw; XSetWindowAttributes xswa; char *p; if (nummenus >= MAXMENUS) { fprintf(stderr, "too many menus\n"); exit(1); } p = rindex(val, '%'); *p = 0; /* nuke the %t */ menu[n].title = strdup(val); menu[n].titlewidth = maxw = XTextWidth(textfont, val, strlen(val)); while (val = strtok((char *) 0, "|")) { menu[n].item[menu[n].nitems++] = strdup(val); w = XTextWidth(textfont, val, strlen(val)); if (w > maxw) maxw = w; if (menu[n].nitems >= MAXMENUITEMS) { fprintf(stderr, "too many menu items\n"); exit(1); } } menu[n].w = maxw + 2 * MENUPADW; menu[n].h = (menu[n].nitems + 1) * (fontheight + MENUPADH) + MENUPADTITLE; xswa.background_pixmap = None; xswa.save_under = True; xswa.event_mask = ExposureMask; xswa.override_redirect = True; mask = CWBackPixmap | CWEventMask | CWSaveUnder | CWOverrideRedirect; menu[n].win = XCreateWindow(dsp, root, 0, 0, menu[n].w + SHADE, menu[n].h + SHADE, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &xswa); return n; } static void displayitem(menu, i, fg, bg) MenuStruct *menu; int i; long fg; long bg; { XSetForeground(dsp, gc, bg); XFillRectangle(dsp, menu->win, gc, 1, MENUPADTITLE + (fontheight + MENUPADH) * i, menu->w - 1, (fontheight + MENUPADH)); XSetForeground(dsp, gc, fg); XDrawString(dsp, menu->win, gc, MENUPADW, MENUPADTITLE + (fontheight + MENUPADH) * i + fontascent, menu->item[i - 1], strlen(menu->item[i - 1])); } void XDrawOString(d, w, g, x, y, s, n) { XSetForeground(dsp, gc, black); XDrawString(d, w, g, x - 1, y - 1, s, n); XDrawString(d, w, g, x, y - 1, s, n); XDrawString(d, w, g, x + 1, y - 1, s, n); XDrawString(d, w, g, x - 1, y, s, n); XDrawString(d, w, g, x + 1, y, s, n); XDrawString(d, w, g, x - 1, y + 1, s, n); XDrawString(d, w, g, x, y + 1, s, n); XDrawString(d, w, g, x + 1, y + 1, s, n); XSetForeground(dsp, gc, white); XDrawString(d, w, g, x, y, s, n); XSetForeground(dsp, gc, black); } int dopup(n) int n; { int menuval = 0; int oldmenuval = 0; int i; XEvent ev; Window r; Window w; int rx; int ry; int wx; int wy; int mask; XMoveWindow(dsp, menu[n].win, menux - 2, menuy - fontheight - MENUPADH - MENUPADTITLE / 2); XMapRaised(dsp, menu[n].win); do { XNextEvent(dsp, &ev); } while (ev.type != Expose); XSetForeground(dsp, gc, white); XFillRectangle(dsp, menu[n].win, gc, 0, 0, menu[n].w, menu[n].h); XSetForeground(dsp, gc, black); XDrawRectangle(dsp, menu[n].win, gc, 0, 0, menu[n].w, menu[n].h); XSetFillStyle(dsp, gc, FillStippled); XFillRectangle(dsp, menu[n].win, gc, menu[n].w, SHADE, SHADE, menu[n].h); XFillRectangle(dsp, menu[n].win, gc, SHADE, menu[n].h, menu[n].w - SHADE, SHADE); XSetFillStyle(dsp, gc, FillSolid); XDrawOString(dsp, menu[n].win, gc, (menu[n].w - menu[n].titlewidth) / 2, MENUPADH + fontascent, menu[n].title, strlen(menu[n].title)); XDrawRectangle(dsp, menu[n].win, gc, 2, 2, menu[n].w - 4, MENUPADH + fontheight + MENUPADTITLE / 2 - 4); XDrawLine(dsp, menu[n].win, gc, 0, MENUPADH + fontheight + MENUPADTITLE / 2, menu[n].w, MENUPADH + fontheight + MENUPADTITLE / 2); for (i = 1; i <= menu[n].nitems; i++) displayitem(&menu[n], i, black, white); do { XQueryPointer(dsp, menu[n].win, &r, &w, &rx, &ry, &wx, &wy, &mask); if (wx > 0 && wx < menu[n].w && wy > MENUPADTITLE + fontheight + MENUPADH && wy < MENUPADTITLE + (fontheight + MENUPADH) * (1 + menu[n].nitems)) { menuval = (wy - MENUPADTITLE) / (fontheight + MENUPADH); if (oldmenuval != menuval) { if (oldmenuval) displayitem(&menu[n], oldmenuval, black, white); displayitem(&menu[n], menuval, white, black); oldmenuval = menuval; } } else if (oldmenuval) { displayitem(&menu[n], oldmenuval, black, white); oldmenuval = menuval = 0; } } while (mask & Button3Mask); XUnmapWindow(dsp, menu[n].win); return menuval; } void RGBmode() { /* NOP */ } void gconfig() { /* NOP */ } void glcompat() { /* NOP */ } void subpixel() { /* NOP */ } void setpattern() { /* NOP */ } void reshapeviewport() { /* NOP */ } void qdevice(mask) int mask; { /* NOP */ } SHAR_EOF fi if test -f 'gl.h' then echo shar: "will not over-write existing file 'gl.h'" else cat << \SHAR_EOF > 'gl.h' #ident "@(#)gl.h 1.1 91/02/16 GL" /* * gl.h - the beginnings of the defines to keep SGI GL programs happy. */ extern long mytimes(); #define REDRAW 0 #define UPARROWKEY 100 #define DOWNARROWKEY 101 #define RIGHTSHIFTKEY 103 #define LEFTMOUSE 200 #define MIDDLEMOUSE 201 #define MENUBUTTON 202 #define MOUSEX 0 #define MOUSEY 1 #define times mytimes #define GLC_OLDPOLYGON 0 SHAR_EOF fi if test -f 'device.h' then echo shar: "will not over-write existing file 'device.h'" else cat << \SHAR_EOF > 'device.h' #ident "@(#)device.h 1.1 91/02/16 GL" /* * device.h - empty file to keep SGI GL programs happy. */ SHAR_EOF fi exit 0 # End of shell archive -- ______________________________________________________________________ Patrick J. Naughton email: naughton@sun.com Sun Laboratories voice: (415) 336 - 1080
naughton@wind.Eng.Sun.COM (Patrick Naughton) (02/17/91)
In article <8089@exodus.Eng.Sun.COM>, I wrote: |> In article <85040@sgi.sgi.com>, (Paul Haeberli) writes: |> |> Here's a little program that uses a very simple dynamics model |> |> to draw caligraphic strokes. Please give it a try if you have |> |> an IRIS workstation. |> |> |> |> paul haeberli |> |> paul@sgi.com |> |> 415-962-3665 |> |> |> |> ... dynadraw.c deleted ... |> |> Here's another set of X11 compatibility routines for us Paul Haeberli |> fans without IRISes... |> I forgot that many comp.windows.x readers didn't see Paul's stuff on comp.graphics, so I put his last three GL programs he posted there plus my hacked up GL->X11 conversion routines on expo:contrib/glx.shar.Z -Patrick -- ______________________________________________________________________ Patrick J. Naughton email: naughton@sun.com Sun Laboratories voice: (415) 336 - 1080