|
From lhf@csgrs6k4.uwaterloo.ca Thu Feb 22 16:55:15 1996
Received: from csgrs6k4.uwaterloo.ca by world.std.com (5.65c/Spike-2.0)
id AA29109; Thu, 22 Feb 1996 11:55:16 -0500
Received: by csgrs6k4.uwaterloo.ca (AIX 3.2/UCB 5.64/4.03UW)
id AA16175; Thu, 22 Feb 1996 11:55:15 -0500
Date: Thu, 22 Feb 1996 11:55:15 -0500
From: lhf@csgrs6k4.uwaterloo.ca (Luiz Henrique de Figueiredo)
Message-Id: <9602221655.AA16175@csgrs6k4.uwaterloo.ca>
To: wware@world.std.com
Subject: Re: Q: drawing program under X
Status: R
use the code below as a starting point.
it sould be easy to add a main program that read the lines as you described
and calls the appropriate function.
to have things drawn in the window as soon as their commands have been
received, call dvflush.
--lhf
/*
* dv/X11.c
* device primitives for X11
* Luiz Henrique de Figueiredo (lhf@visgraf.impa.br)
* 22 Nov 95
*/
#include
#include
#include
#include
#include
#include
#include
#include "gp.h"
#define vector(n,t) ( (t*) malloc((n)*sizeof(t)) )
#define revector(p,n) ( (void*) realloc(p,(n)*sizeof(*p)) )
#define colormapsize 256 /* was DisplayCells(display,screen) */
/* add PointerMotionMask for idle motion report */
#define EventMask \
(ButtonPressMask|ButtonReleaseMask|KeyPressMask|ButtonMotionMask|ExposureMask)
#define Idle (-1)
typedef unsigned long Pixel;
static Box dv;
static Display* display;
static int screen;
static Window window;
static Drawable canvas;
static Pixmap back=0;
static GC gc;
static Colormap cm;
static Cursor waitcursor;
static Cursor closecursor;
static XFontStruct* font=NULL;
static int color=1;
static int marksize=3;
static char* marktype=".";
static Pixel* colormap;
static int polymode=0;
static XPoint* point=NULL;
static int points=0;
static int maxpoints=0;
static void waitinput (Cursor cursor);
static void waitevent (int mask);
Box* dvopen(char* name)
{
display=XOpenDisplay(NULL);
if (display==NULL)
{
fprintf(stderr,"%s: cannot open X display [%s]\n",name,XDisplayName(NULL));
exit(1);
}
screen=DefaultScreen(display);
gc=DefaultGC(display,screen);
cm=DefaultColormap(display,screen);
font=XQueryFont(display,XGContextFromGC(gc));
waitcursor=XCreateFontCursor(display,XC_icon);
closecursor=XCreateFontCursor(display,XC_pirate);
colormap=vector(colormapsize,Pixel);
colormap[0]=WhitePixel(display,screen);
colormap[1]=BlackPixel(display,screen);
{ /* in case use color before binding */
int c;
for (c=2; c=0)
usleep(1000*t); /* sleep t miliseconds */
else
waitinput(waitcursor);
}
int dvpalette(int c, char* name)
{
XColor C;
if (c<0 || c>=colormapsize)
return 0;
if (XParseColor(display,cm,name,&C) && XAllocColor(display,cm,&C))
{
colormap[c]=C.pixel;
if (c==0) /* color 0 is background */
{
XSetWindowBackground(display,window,colormap[c]);
XSetBackground(display,gc,colormap[c]);
XClearWindow(display,window);
}
return 1;
}
else
return 0;
}
#define C(x) round((x)*(0x0ffff))
int dvrgb(int c, real r, real g, real b)
{
char name[]="#RRRRGGGGBBBB";
sprintf(name,"#%04X%04X%04X",C(r),C(g),C(b));
return dvpalette(c,name);
}
#undef C
int dvcolor(int c)
{
if (c<0 || c>=colormapsize)
return -colormapsize;
else
{
int old=color;
color=c;
XSetForeground(display,gc,colormap[c]);
return old;
}
}
int dvfont(char* name)
{
XFontStruct* f=XLoadQueryFont(display,name);
if (f==NULL)
return 0;
else
{
XSetFont(display,gc,f->fid);
font=f;
return 1;
}
}
void dvmark(int size, char* mark)
{
if (size>0) marksize=size;
if (mark!=NULL && *mark!=0) marktype=mark;
}
void dvclip(int xmin, int xmax, int ymin, int ymax)
{
XRectangle r;
r.x=xmin;
r.y=ymin;
r.width=xmax-xmin+1;
r.height=ymax-ymin+1;
XSetClipRectangles(display,gc,0,0,&r,1,Unsorted);
}
void dvline(int x1, int y1, int x2, int y2)
{
XDrawLine(display,canvas,gc,x1,y1,x2,y2);
}
void dvbox(int xmin, int xmax, int ymin, int ymax)
{
XFillRectangle(display,canvas,gc,xmin,ymin,xmax-xmin+1,ymax-ymin+1);
}
void dvtri(int x1, int y1, int x2, int y2, int x3, int y3)
{
dvbegin('f');
dvpoint(x1,y1);
dvpoint(x2,y2);
dvpoint(x3,y3);
dvend();
}
#define at(a,b) (m[0]==a && m[1]==b)
void dvtext(int x, int y, char* s, char* m)
{
int n=strlen(s);
int w=XTextWidth(font,s,n);
int h=font->ascent+font->descent;
int opaque=0;
y-=font->descent-1;
if (m==NULL) m="sw";
if (m[0]=='!') { opaque=1; ++m; } else opaque=0;
if (0);
else if (at('n', 0 )) { x-=w/2; y+=h; }
else if (at('n','e')) { x-=w; y+=h; }
else if (at('n','w')) { y+=h; }
else if (at('s', 0 )) { x-=w/2; }
else if (at('s','e')) { x-=w; }
else if (at('s','w')) { }
else if (at('e', 0 )) { x-=w; y+=h/2; }
else if (at('w', 0 )) { y+=h/2; }
else if (at('c', 0 )) { x-=w/2; y+=h/2; }
if (opaque)
XDrawImageString(display,canvas,gc,x,y,s,n);
else
XDrawString(display,canvas,gc,x,y,s,n);
}
void dvcircle(int x, int y, int r)
{
XDrawArc(display,canvas,gc,x-r,y-r,2*r,2*r,0,360*64);
}
void dvplot(int x, int y)
{
int size=marksize;
char* m;
for (m=marktype; *m!=0; m++)
switch (*m)
{
XSegment s[5]; XPoint p[5];
int dx,dy;
default:
case '.':
XDrawPoint(display,canvas,gc,x,y);
break;
case 'o':
XDrawArc(display,canvas,gc,x-size,y-size,2*size,2*size,0,360*64);
break;
case 'O':
XFillArc(display,canvas,gc,x-size,y-size,2*size,2*size,0,360*64);
break;
case '+':
s[0].x1=x-size; s[0].y1=y; s[0].x2=x+size; s[0].y2=y;
s[1].x1=x; s[1].y1=y-size; s[1].x2=x; s[1].y2=y+size;
XDrawSegments(display,canvas,gc,s,2);
break;
case '*':
dx=size*0.5; dy=size*0.866;
s[0].x1=x-size; s[0].y1=y; s[0].x2=x+size; s[0].y2=y;
s[1].x1=x+dx; s[1].y1=y+dy; s[1].x2=x-dx; s[1].y2=y-dy;
s[2].x1=x+dx; s[2].y1=y-dy; s[2].x2=x-dx; s[2].y2=y+dy;
XDrawSegments(display,canvas,gc,s,3);
break;
case 'x':
dx=size; dy=size;
s[0].x1=x+dx; s[0].y1=y+dy; s[0].x2=x-dx; s[0].y2=y-dy;
s[1].x1=x+dx; s[1].y1=y-dy; s[1].x2=x-dx; s[1].y2=y+dy;
XDrawSegments(display,canvas,gc,s,2);
break;
case 'b':
XDrawRectangle(display,canvas,gc,x-size,y-size,2*size,2*size);
break;
case 'B':
XFillRectangle(display,canvas,gc,x-size,y-size,2*size+1,2*size+1);
break;
case 'd':
p[0].x=x-size; p[0].y=y;
p[1].x=x; p[1].y=y+size;
p[2].x=x+size; p[2].y=y;
p[3].x=x; p[3].y=y-size;
p[4].x=x-size; p[4].y=y;
XDrawLines(display,canvas,gc,p,5,CoordModeOrigin);
break;
case 'D':
p[0].x=x-size; p[0].y=y;
p[1].x=x; p[1].y=y+size;
p[2].x=x+size; p[2].y=y;
p[3].x=x; p[3].y=y-size;
p[4].x=x-size; p[4].y=y;
XFillPolygon(display,canvas,gc,p,5,Convex,CoordModeOrigin);
break;
}
}
void dvbegin(int mode)
{
if (point==NULL) point=vector(maxpoints=16,XPoint);
polymode=mode;
points=0;
}
int dvpoint(int x, int y) /* should check XMaxRequestSize */
{
int i=points++;
if (i>=maxpoints) point=revector(point,maxpoints*=2);
point[i].x=x;
point[i].y=y;
return points;
}
void dvend(void)
{
switch (polymode)
{
case 'p': /* closed polygonal line */
dvpoint(point[0].x,point[0].y);
case 'l': /* open polygonal line */
XDrawLines(display,canvas,gc,point,points,CoordModeOrigin);
break;
case 'f': /* filled polygon */
dvpoint(point[0].x,point[0].y);
XFillPolygon(display,canvas,gc,point,points,Complex,CoordModeOrigin);
break;
case 'm': /* polymarker (only dots) */
XDrawPoints(display,canvas,gc,point,points,CoordModeOrigin);
break;
}
polymode=0;
points=0;
}
char* dvevent(int wait, int* x, int* y)
{
XEvent event;
unsigned int state=0;
if (wait)
XWindowEvent(display,window,EventMask,&event);
else if (!XCheckWindowEvent(display,window,EventMask,&event))
#if 0
return NULL;
#else /* report idle status */
{
Window rw,w ; int rx,ry;
XQueryPointer(display,window,&rw,&w,&rx,&ry,x,y,&state);
event.type=Idle; /* fake event */
}
#endif
{
static char report[]="m123+SCM";
char* r=report;
switch (event.type)
{
case Expose:
*x=100000000+event.xexpose.x*10001+event.xexpose.width;
*y=100000000+event.xexpose.y*10001+event.xexpose.height;
*r++='r';
*r++=(event.xexpose.count!=0) ? '+' : '-'; /* signal last expose */
break;
case ButtonPress:
case ButtonRelease:
state=event.xbutton.state;
*x=event.xbutton.x;
*y=event.xbutton.y;
*r++='b';
*r++='0'+event.xbutton.button;
*r++=(event.type==ButtonPress) ? '+' : '-';
break;
case KeyPress:
case KeyRelease:
report[1]=0;
XLookupString(&event.xkey,report+1,sizeof(report)-1,NULL,NULL);
state=event.xkey.state;
*x=event.xkey.x;
*y=event.xkey.y;
*r++='k';
*r++; /* lazy */
*r++=(event.type==KeyPress) ? '+' : '-';
break;
case MotionNotify:
#if 1
while (XEventsQueued(display,QueuedAfterReading)>0)
{
XEvent ahead;
XPeekEvent(display,&ahead);
if (ahead.type!=MotionNotify) break;
if (ahead.xmotion.window!=window) break;
XWindowEvent(display,window,EventMask,&event);
}
#endif
state=event.xmotion.state;
#if 1
*x=event.xmotion.x;
*y=event.xmotion.y;
#else
{
Window rw,w ; int rx,ry;
XQueryPointer(display,window,&rw,&w,&rx,&ry,x,y,&state);
}
#endif
case Idle:
*r++=(event.type==MotionNotify) ? 'm' : 'i';
if (state&Button1Mask) *r++='1';
if (state&Button2Mask) *r++='2';
if (state&Button3Mask) *r++='3';
*r++='+';
break;
}
if (state&ShiftMask) *r++='S';
if (state&ControlMask) *r++='C';
if (state&Mod1Mask) *r++='M'; /* meta is Mod1*/
*r++=0;
return report;
}
}
static void waitinput(Cursor cursor)
{
XDefineCursor(display,window,cursor);
waitevent(ButtonReleaseMask|KeyPressMask);
XUndefineCursor(display,window);
}
static void waitevent(int mask)
{
XEvent event;
XWindowEvent(display,window,mask,&event);
}
void dvdoublebuffer(int on)
{
if (on)
{
back=XCreatePixmap(display,window,dv.xu,dv.yu,8);
dvbackbuffer();
dvclear(0);
}
else if (back!=0)
{
XFreePixmap(display,back);
back=0;
}
}
void dvswapbuffers(void)
{
XCopyArea(display,back,window,gc,0,0,dv.xu,dv.yu,0,0);
#if 0
XFlush(display);
#endif
}
void dvfrontbuffer(void)
{
canvas=(Drawable) window;
}
void dvbackbuffer(void)
{
canvas=(Drawable) back;
}
------------
/*
* gp.h
* a simple 2d graphics package
* Luiz Henrique de Figueiredo (lhf@visgraf.impa.br)
* 16 Jan 96
*/
#define real double
#define Box gpBox
typedef struct
{
real xmin;
real xmax;
real ymin;
real ymax;
real xu;
real yu;
} Box;
real gpopen (char* name);
void gpclose (int wait);
void gpclear (int wait);
void gpflush (void);
void gpwait (int t);
int gppalette (int c, char* name);
int gprgb (int c, real r, real g, real b);
int gpcolor (int c);
int gpfont (char* name);
void gpmark (int size, char* mark);
void gpline (real x1, real y1, real x2, real y2);
void gpbox (real xmin, real xmax, real ymin, real ymax);
void gptri (real x1, real y1, real x2, real y2, real x3, real y3);
void gptext (real x, real y, char* s, char* mode);
void gpcircle (real x, real y, real r);
void gpplot (real x, real y);
void gpbegin (int c);
int gppoint (real x, real y);
void gpend (void);
char* gpevent (int wait, real* x, real* y);
real gpwindow (real xmin, real xmax, real ymin, real ymax);
real gpviewport (real xmin, real xmax, real ymin, real ymax);
void gpview (real* x, real* y);
void gpunview (real* x, real* y);
void gpmake (void);
#define gpbegin dvbegin
#define gpclear dvclear
#define gpclose dvclose
#define gpcolor dvcolor
#define gpend dvend
#define gpflush dvflush
#define gpfont dvfont
#define gpmark dvmark
#define gppalette dvpalette
#define gprgb dvrgb
#define gpwait dvwait
Box* dvopen (char* name);
void dvclose (int wait);
void dvclear (int wait);
void dvflush (void);
void dvwait (int t);
int dvpalette (int c, char* name);
int dvrgb (int c, real r, real g, real b);
int dvcolor (int c);
int dvfont (char* name);
void dvmark (int size, char* mark);
void dvclip (int xmin, int xmax, int ymin, int ymax);
void dvline (int x1, int y1, int x2, int y2);
void dvbox (int xmin, int xmax, int ymin, int ymax);
void dvtri (int x1, int y1, int x2, int y2, int x3, int y3);
void dvtext (int x, int y, char* s, char* mode);
void dvcircle (int x, int y, int r);
void dvplot (int x, int y);
void dvbegin (int c);
int dvpoint (int x, int y);
void dvend (void);
char* dvevent (int wait, int* x, int* y);
void dvdoublebuffer(int on);
void dvswapbuffers(void);
void dvfrontbuffer(void);
void dvbackbuffer(void);
void dvbufferarea(int xmin, int xmax, int ymin, int ymax);
#ifndef rad
#define rad(a) ((a)*(real)0.01745329252)
#endif
#ifndef round
#define round(x) ((int)((x)+(real)0.5))
#endif
#ifndef min
#define min(x,y) ( ((x)<(y)) ? (x) : (y) )
#endif
#ifndef max
#define max(x,y) ( ((x)>(y)) ? (x) : (y) )
#endif
|