Fun dynamic sketching program for IRISes.
Patrick Naughton
naughton at wind.Eng.Sun.COM
Sun Feb 17 18:37:55 AEST 1991
In article <85040 at sgi.sgi.com>, paul at 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 at 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 at sun.com
Sun Laboratories voice: (415) 336 - 1080
More information about the Comp.sys.sgi
mailing list