This is hplotX11.c in view mode; [Download] [Up]
/*
* hippoplotX.c -- Graphics code for producing pure X displays.
*
*
* Author : Tony Johnson
* Created On : 8 Feb 1992
* Last Modified By: Tony Johnson
* Last Modified On: 8 Feb 1992
* Update Count :
* Status : Revision 1
*
* Copyright (C) 1991 The Board of Trustees of The Leland Stanford
* Junior University. All Rights Reserved.
*
* $Id: hplotX11.c,v 5.0 1993/08/17 21:56:10 rensing Exp $
*/
#include "hplotX11.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
GLOB_QUAL const char hippoplotX11_c_rcsid[] =
"$Id: hplotX11.c,v 5.0 1993/08/17 21:56:10 rensing Exp $";
GLOB_QUAL const char hippoplotX11_h_rcsid[] = HIPPOPLOTX11_H_RCSID;
#define FontName\
"-Adobe-New Century Schoolbook-Bold-R-Normal--*-*-*-*-*-*-*-*"
#define MAXFONTS 30
#define MAXCACHE 20
#define min(A,B) ((A>B) ? B : A)
/* These are for passing info from Histo class: */
static Display *h_display;
static Drawable h_drawable;
static GC h_gc;
static Font h_font[MAXFONTS];
static XFontStruct *h_fontStruct;
static int h_nFonts;
static char **h_fontNames;
static int h_depth;
static int h_color;
static Screen *h_screen;
static init = 0;
/* All scaling info: */
static struct {
float x;
float y;
int xMarg;
int yMarg;
float xOrig;
float yOrig;
} Scale, Convert;
/* The Data-coords limits: */
static struct {
float xmin;
float xmax;
float ymin;
float ymax;
} Limit;
static void drawStipple2D_X11(int nXBins,
int nYBins,
float minBin,
float maxBin,
float bins[]);
static void ColorError();
static int XScale(float x)
{
return (x - Scale.xOrig)*Scale.x + Scale.xMarg;
}
static int YScale(float y)
{
return Scale.yMarg - (y - Scale.yOrig)*Scale.y;
}
static int XConvert(float x)
{
return (x - Convert.xOrig)*Convert.x + Convert.xMarg;
}
static int YConvert(float y)
{
return Convert.yMarg - (y - Convert.yOrig)*Convert.y;
}
void initPlot_X11(Display *disp, Screen *screen, Drawable drawable, GC gc)
{
h_display = disp;
h_drawable = drawable;
h_gc = gc;
h_screen = screen;
if (!init)
{
int i;
init = 1;
h_fontNames = XListFontsWithInfo(disp,FontName,MAXFONTS,
&h_nFonts,&h_fontStruct);
for (i=0; i<h_nFonts; i++) h_font[i] = 0;
}
/* Are we in color? */
h_color = (DefaultVisualOfScreen(h_screen)->class == PseudoColor);
}
static void ColorError()
{
static Reported = 0;
if (Reported++) return;
printf("\nXHippo: Unable to allocate required colormap entries\n");
}
void setHistoCoords_X11(rectangle *draw,
rectangle *margin,
rectangle *data)
{
unsigned int width, height, border;
int x,y;
Window root;
/* Get overall width and height from window. */
XGetGeometry(h_display,h_drawable,&root,&x,&y,&width,
&height,&border,&h_depth);
/* Remember margin is in points; data is in data coords. */
Convert.x = width/draw->size.width;
Convert.y = height/draw->size.height;
Convert.xMarg = 0;
Convert.yMarg = height;
Convert.xOrig = draw->origin.x;
Convert.yOrig = draw->origin.y;
Scale.x = (Convert.x * margin->size.width)/(data->size.width);
Scale.y = (Convert.y * margin->size.height)/(data->size.height);
Scale.xMarg = XConvert(margin->origin.x);
Scale.yMarg = YConvert(margin->origin.y);
Scale.xOrig = data->origin.x;
Scale.yOrig = data->origin.y;
Limit.xmin = data->origin.x;
Limit.xmax = data->size.width + data->origin.x;
Limit.ymin = data->origin.y;
Limit.ymax = data->size.height + data->origin.y;
#ifdef DEBUG
printf ("setupX: X scale = %f, Y scale = %f\n", Scale.x, Scale.y);
#endif
}
/* Put the message text at the indicated x-y position (Note, x and y
* are in points):
*/
void drawText_X11(char *message,
float x,
float y,
float fontHeight,
float angle,
char xalign,
char yalign)
{
int xx = XConvert(x);
int yy = YConvert(y);
int width, dir, ascent, descent;
int length = strlen(message);
int i, n, size;
double sinA = sin(angle), cosA = cos(angle);
XCharStruct overall;
/* Decide which font to use */
int fontSize = min(Convert.x , Convert.y) * fontHeight;
size = 0;
for (i=0; i<h_nFonts; i++)
{
int h = h_fontStruct[i].ascent + h_fontStruct[i].descent;
if (h <= fontSize && h > size)
{
size = h;
n = i;
}
}
if (size == 0)
{
size = 99999;
for (i=0; i<h_nFonts; i++)
{
int h = h_fontStruct[i].ascent + h_fontStruct[i].descent;
if (h < size)
{
size = h;
n = i;
}
}
}
if (h_font[n] == 0)
{
h_fontStruct[n] = *XLoadQueryFont(h_display,h_fontNames[n]);
h_font[n] = h_fontStruct[n].fid;
}
#ifdef DEBUG
printf("fontHeight,Convert.x,Convert.y,angle,font %f,%f,%f,%f\n%s",
fontHeight,Convert.x,Convert.y,angle,h_fontNames[n]);
#endif
XSetFont(h_display,h_gc,h_font[n]);
XTextExtents(&h_fontStruct[n],message,length,&dir,
&ascent,&descent,&overall);
width = overall.width;
ascent = overall.ascent;
descent = overall.descent;
switch (xalign)
{
case 'C':
case 'c':
xx -= cosA*width/2 + sinA*(ascent - descent)/2;
break;
case 'R':
case 'r':
xx -= cosA*width + sinA*ascent;
break;
case 'L':
case 'l':
default:
xx += sinA*ascent;
break;
}
switch (yalign)
{
case 'C':
case 'c':
yy += cosA*(ascent - descent)/2 - sinA*width/2;
break;
case 'T':
case 't':
yy += cosA*ascent - sinA*width;
break;
case 'B':
case 'b':
default:
yy -= cosA*descent;
break;
}
if (angle!=0)
/*
* There is no good way to deal with angled text prior to X11R5.
* The following is an inelegant work around. This can probably
* be done better with X11R5. This code is currently set up to rotate
* by a fixed 90 degress (ie angle is ignored).
*/
{
int height = ascent + descent;
int i;
static struct {
char *text;
Pixmap map;
} cache[MAXCACHE];
static int Ncache = 0;
for (i=0; i<Ncache; i++)
{
if (strcmp(cache[i].text,message) == 0) break;
}
if (i<Ncache)
{
XCopyArea(h_display,cache[i].map,h_drawable,
h_gc,0,0,height,width,xx,yy);
}
else
{
int i,j;
XImage *image, *rimage;
XGCValues values;
GC gc_temp = XCreateGC(h_display,h_drawable,0,&values);
Pixmap New = XCreatePixmap(h_display,h_drawable,
width,height,h_depth);
Pixmap Rot = XCreatePixmap(h_display,h_drawable,
height,width,h_depth);
XGetGCValues(h_display,h_gc,GCBackground,&values);
values.foreground = values.background;
XChangeGC(h_display,gc_temp,GCForeground,&values);
XFillRectangle(h_display,New,gc_temp,0,0,width,height);
XFreeGC(h_display,gc_temp);
XDrawString(h_display,New,h_gc,0,ascent,message,length);
image = XGetImage(h_display,New,0,0,width,height,
AllPlanes,XYPixmap);
rimage = XGetImage(h_display,Rot,0,0,height,width,
AllPlanes,XYPixmap);
for (i=0; i<width; i++)
for (j=0; j<height; j++)
XPutPixel(rimage,j,width-i-1,XGetPixel(image,i,j));
XPutImage(h_display,Rot,h_gc,rimage,0,0,0,0,height,width);
XCopyArea(h_display,Rot,h_drawable,h_gc,0,0,height,width,xx,yy);
XFreePixmap(h_display,New);
XDestroyImage(image);
XDestroyImage(rimage);
if (Ncache == MAXCACHE)
{
XFreePixmap(h_display,cache[0].map);
free(cache[0].text);
for (i=1; i<MAXCACHE; i++) cache[i-1] = cache[i];
Ncache--;
}
cache[Ncache].map = Rot;
cache[Ncache].text = strcpy(malloc(length+1),message);
Ncache++;
}
}
else { XDrawString(h_display,h_drawable,h_gc,xx,yy,message,length); }
}
void drawMag_X11(float x, float y,
int mag, float fontsize)
/* x and y are in device coords (points). */
{
char buffer[12];
sprintf(buffer,"%d",mag);
drawText_X11("x10",x,y,fontsize,0,'r','c');
drawText_X11(buffer,x,y,fontsize,0,'l','b');
}
void drawXTicks_X11(float *x,
int nt,
float tickwidth,
int side)
{
XSegment *segs = (XSegment *) malloc(nt*sizeof(XSegment));
XSegment *ns = segs;
int i;
short y1, y2;
if (side == 0)
{
y1 = YScale(Limit.ymin);
y2 = y1 - Convert.y * tickwidth;
}
else
{
y1 = YScale(Limit.ymax) + 1;
y2 = y1 + Convert.y * tickwidth;
}
for (i = 0; i < nt; i++)
{
ns->x1 = XScale(*x++);
ns->x2 = ns->x1;
ns->y1 = y1;
ns->y2 = y2;
ns++;
}
XSetLineAttributes(h_display,h_gc,0,LineSolid,CapButt,JoinMiter);
XDrawSegments(h_display,h_drawable,h_gc,segs,nt);
free(segs);
}
void drawYTicks_X11(float* y,
int nt,
float tickwidth,
int side)
{
XSegment *segs = (XSegment *) malloc(nt*sizeof(XSegment));
XSegment *ns = segs;
int i;
short x1, x2;
if (side == 0)
{
x1 = XScale(Limit.xmin) + 1;
x2 = x1 + Convert.x * tickwidth;
}
else
{
x1 = XScale(Limit.xmax);
x2 = x1 - Convert.x * tickwidth;
}
for (i = 0; i < nt; i++)
{
ns->y1 = YScale(*y++);
ns->y2 = ns->y1;
ns->x1 = x1;
ns->x2 = x2;
ns++;
}
XSetLineAttributes(h_display,h_gc,0,LineSolid,CapButt,JoinMiter);
XDrawSegments(h_display,h_drawable,h_gc,segs,nt);
free(segs);
}
void drawRect_X11(float x, float y,
float width, float height)
/* all args are in window coords */
{
XDrawRectangle(h_display, h_drawable, h_gc, XConvert(x), YConvert(y),
XConvert(width), XConvert(height));
#ifdef DEBUG
printf("drawRect_X11: rect at (%d, %d) size (%d, %d)\n",
XConvert(x), YConvert(y), XConvert(width),YConvert(height));
#endif
}
void drawFilledRect_X11(float x, float y,
float width, float height,
float grey)
/* all args are in window coords */
{
int xx = XConvert(x);
int yy = YConvert(y);
int ww = Convert.x * width;
int hh = Convert.y * height;
int color = 256*grey;
XSetForeground(h_display, h_gc, color);
XFillRectangle(h_display, h_drawable, h_gc, xx, yy, ww, hh);
#ifdef DEBUG
printf("drawFilledRect_X11: rect at (%d, %d) size (%d, %d) color (%d)\n",
xx, yy, ww, hh, color);
#endif
}
void shade_X11(float xlow, float xhigh,
float ylow, float yhigh )
/* all args are in data coords */
{
int xx = XConvert(xlow);
int yy = YConvert(yhigh);
int ww = XConvert(xhigh) - xx;
int hh = YConvert(ylow) - yy;
Pixmap Stipple;
static char data[] = {0x02, 0x01};
Stipple = XCreatePixmapFromBitmapData(h_display,h_drawable,data,2,2,0,1,1);
XSetStipple(h_display, h_gc, Stipple);
XSetFillStyle(h_display,h_gc,FillStippled);
XFillRectangle(h_display, h_drawable, h_gc, xx, yy, ww, hh);
XSetFillStyle(h_display,h_gc,FillSolid);
XFreePixmap(h_display,Stipple);
#ifdef DEBUG
printf("drawFilledRect_X11: rect at (%f, %f) to (%f, %f)\n",
xlow, ylow, xhigh,yhigh);
#endif
}
void drawLine_X11(float *xy, int nxy, linestyle_t ls)
{
XPoint *points = (XPoint *) malloc(nxy*sizeof(XPoint));
XPoint *np = points;
int i;
for (i = 0; i < nxy; i++)
{
np->x = XScale(*xy++);
np->y = YScale(*xy++);
np++;
}
switch (ls)
{
char dashlist[4];
case SOLID:
default:
XSetLineAttributes(h_display,h_gc,0,LineSolid,CapButt,JoinMiter);
break;
case DASH:
dashlist[0] = 4;
dashlist[1] = 4;
XSetDashes(h_display,h_gc,0,dashlist,2);
XSetLineAttributes(h_display,h_gc,0,LineOnOffDash,CapButt,JoinMiter);
break;
case DOT:
dashlist[0] = 1;
dashlist[1] = 2;
XSetDashes(h_display,h_gc,0,dashlist,2);
XSetLineAttributes(h_display,h_gc,0,LineOnOffDash,CapButt,JoinMiter);
break;
case DOTDASH:
dashlist[0] = 4;
dashlist[1] = 2;
dashlist[2] = 1;
dashlist[3] = 2;
XSetDashes(h_display,h_gc,0,dashlist,4);
XSetLineAttributes(h_display,h_gc,0,LineOnOffDash,CapButt,JoinMiter);
break;
}
XDrawLines(h_display,h_drawable,h_gc,points,nxy,CoordModeOrigin);
free(points);
}
void drawPoints_X11(float xy[],
int nxy,
int symbol,
float symbolsize)
{
XRectangle *recs, *r;
XSegment *segs, *s;
int i;
short simsize = min(Convert.x , Convert.y) * symbolsize/2;
short width = 4, height = 4, halfwidth=2, halfheight=2;
if (simsize<1) simsize=1;
halfwidth = simsize;
halfheight = simsize;
width = simsize*2;
height = simsize*2;
switch (symbol)
{
case SQUARE:
case SOLIDSQUARE:
default:
recs = (XRectangle *) malloc(nxy*sizeof(XRectangle));
r = recs;
for (i=0; i<nxy; i++)
{
r->x = XScale(*xy++) - halfwidth;
r->y = YScale(*xy++) - halfheight;
r->width = width;
r->height = height;
r++;
}
if (symbol == SOLIDSQUARE) XFillRectangles(h_display,h_drawable,
h_gc,recs,nxy);
else XDrawRectangles(h_display,h_drawable,
h_gc,recs,nxy);
free(recs);
break;
case PLUS:
case TIMES:
segs = (XSegment *) malloc(nxy*sizeof(XSegment)*2);
s = segs;
if (symbol==TIMES)
for (i=0; i<nxy; i++)
{
short x = XScale(*xy++);
short y = YScale(*xy++);
s->x1 = x-halfwidth;
s->x2 = x+halfwidth;
s->y1 = y-halfheight;
s->y2 = y+halfheight;
s++;
s->x1 = x-halfwidth;
s->x2 = x+halfwidth;
s->y1 = y+halfheight;
s->y2 = y-halfheight;
s++;
}
else
for (i=0; i<nxy; i++)
{
short x = XScale(*xy++);
short y = YScale(*xy++);
s->x1 = x-halfwidth;
s->x2 = x+halfwidth;
s->y1 = y;
s->y2 = y;
s++;
s->x1 = x;
s->x2 = x;
s->y1 = y-halfheight;
s->y2 = y+halfheight;
s++;
}
XSetLineAttributes(h_display,h_gc,0,LineSolid,CapButt,JoinMiter);
XDrawSegments(h_display,h_drawable,h_gc,segs,nxy*2);
free(segs);
}
}
void drawXError_X11(float xy[],
float errs[],
int npts)
{
XSegment *segs = (XSegment *) malloc(3*npts*sizeof(XSegment));
XSegment *ns = segs;
int i;
short halfwidth = 2;
for (i = 0; i < npts; i++)
{
short y, xhi, xlo;
xy++; /* ignore x value */
y = YScale(*xy++);
xhi = XScale(*errs++);
xlo = XScale(*errs++);
ns->y1 = y;
ns->y2 = y;
ns->x1 = xlo;
ns->x2 = xhi;
ns++;
ns->y1 = y+halfwidth;
ns->y2 = y-halfwidth;
ns->x1 = xlo;
ns->x2 = xlo;
ns++;
ns->y1 = y+halfwidth;
ns->y2 = y-halfwidth;
ns->x1 = xhi;
ns->x2 = xhi;
ns++;
}
XSetLineAttributes(h_display,h_gc,0,LineSolid,CapButt,JoinMiter);
XDrawSegments(h_display,h_drawable,h_gc,segs,3*npts);
free(segs);
}
void drawYError_X11(float xy[],
float errs[],
int npts)
{
XSegment *segs = (XSegment *) malloc(3*npts*sizeof(XSegment));
XSegment *ns = segs;
int i;
short halfwidth = 2;
for (i = 0; i < npts; i++)
{
short x, yhi, ylo;
x = XScale(*xy++);
xy++; /* ignore y value */
yhi = YScale(*errs++);
ylo = YScale(*errs++);
ns->x1 = x;
ns->x2 = x;
ns->y1 = ylo;
ns->y2 = yhi;
ns++;
ns->x1 = x+halfwidth;
ns->x2 = x-halfwidth;
ns->y1 = ylo;
ns->y2 = ylo;
ns++;
ns->x1 = x+halfwidth;
ns->x2 = x-halfwidth;
ns->y1 = yhi;
ns->y2 = yhi;
ns++;
}
XSetLineAttributes(h_display,h_gc,0,LineSolid,CapButt,JoinMiter);
XDrawSegments(h_display,h_drawable,h_gc,segs,3*npts);
free(segs);
}
static void drawStipple2D_X11(int nXBins,
int nYBins,
float minBin,
float maxBin,
float bins[])
{
float xBinWidth = (Limit.xmax - Limit.xmin)/nXBins;
float yBinWidth = (Limit.ymax - Limit.ymin)/nYBins;
float x = Limit.xmin;
float y = Limit.ymin;
float scale = 15.0 / (maxBin - minBin);
int i,j;
int xx = XScale(Limit.xmin);
int yy = YScale(Limit.ymin);
int ww, hh;
unsigned long mask = GCForeground | GCBackground | GCFillStyle | GCStipple;
XGCValues values;
Pixmap Stipple[16];
GC temp_gc[16];
static char data[16][4] = {
{0x0f, 0x0f, 0x0f, 0x0f},
{0x0f, 0x0e, 0x0f, 0x0f},
{0x0f, 0x0e, 0x07, 0x0f},
{0x0d, 0x0e, 0x07, 0x0f},
{0x0d, 0x0e, 0x07, 0x0b},
{0x0d, 0x0e, 0x05, 0x0b},
{0x05, 0x0e, 0x05, 0x0b},
{0x05, 0x0a, 0x05, 0x0b},
{0x05, 0x0a, 0x05, 0x0a},
{0x05, 0x0a, 0x01, 0x0a},
{0x01, 0x0a, 0x01, 0x0a},
{0x01, 0x0a, 0x00, 0x0a},
{0x00, 0x0a, 0x00, 0x0a},
{0x00, 0x02, 0x00, 0x0a},
{0x00, 0x02, 0x00, 0x08},
{0x00, 0x02, 0x00, 0x00}};
for (i=0; i<16; i++)
Stipple[i] = XCreatePixmapFromBitmapData(h_display,h_drawable,
data[i],4,4,0,1,1);
values.foreground = BlackPixelOfScreen(h_screen);
values.background = WhitePixelOfScreen(h_screen);
values.fill_style = FillOpaqueStippled;
for (i=0; i<16; i++)
{
values.stipple = Stipple[i];
temp_gc[i] = XCreateGC(h_display,h_drawable,mask,&values);
}
XFillRectangle(h_display,h_drawable,temp_gc[0],xx,YScale(Limit.ymax),
(XScale(Limit.xmax)-xx),(yy-YScale(Limit.ymax)));
for (i=0; i<nXBins; i++)
{
x += xBinWidth;
ww = XScale(x) - xx;
for (j=0; j<nYBins; j++)
{
int ss = scale * (*bins++ - minBin);
y += yBinWidth;
hh = yy - YScale(y);
yy -= hh;
if (ss!=0)
XFillRectangle(h_display,h_drawable,temp_gc[ss],xx,yy,ww,hh);
}
xx += ww;
yy = YScale(Limit.ymin);
y = Limit.ymin;
}
for (i=0; i<16; i++)
{
XFreePixmap(h_display,Stipple[i]);
XFreeGC(h_display,temp_gc[i]);
}
}
void drawColor2D_X11(int nXBins,
int nYBins,
float minBin,
float maxBin,
float bins[],
int fullColor)
{
float xBinWidth = (Limit.xmax - Limit.xmin)/nXBins;
float yBinWidth = (Limit.ymax - Limit.ymin)/nYBins;
float x = Limit.xmin;
float y = Limit.ymin;
float scale = 90.0 / (maxBin - minBin);
int i,j;
int xx = XScale(Limit.xmin);
int yy = YScale(Limit.ymin);
int ww, hh;
static int GotColorMap = 0;
static int GotGreyMap = 0;
Colormap Map;
static XColor Color[91];
static XColor Grey[91];
XColor *ColorsUsed;
GC temp_gc;
static struct {
int red;
int green;
int blue;
}
rainbow[10] ={{0 , 0, 0}, /* black */
{33422, 15728, 553}, /* brown */
{23912, 14548, 33947}, /* violet */
{15217, 17377, 41142}, /* indigo */
{ 0, 0, 55049}, /* blue */
{ 0, 50078, 199}, /* green */
{62193, 60816, 0}, /* yellow */
{65535, 28180, 1310}, /* orange */
{65535, 1310, 0}, /* red */
{65535, 65535, 65535}}; /* white */
if (!h_color)
{
drawStipple2D_X11(nXBins,nYBins,minBin,maxBin,bins);
return;
}
temp_gc = XCreateGC(h_display,h_drawable,NULL,0);
if (fullColor != 0 && GotColorMap++ == 0)
{
int i, j, k=0;
Map = DefaultColormapOfScreen(h_screen);
for (i=0; i<9; i++)
{
for (j=0; j<10; j++)
{
Color[k].red = rainbow[i].red*(10-j)/10 +
rainbow[i+1].red*j/10;
Color[k].blue = rainbow[i].blue*(10-j)/10 +
rainbow[i+1].blue*j/10;
Color[k].green = rainbow[i].green*(10-j)/10 +
rainbow[i+1].green*j/10;
if (!XAllocColor(h_display,Map,&Color[k])) ColorError();
k++;
}
}
Color[k].red = rainbow[9].red;
Color[k].blue = rainbow[9].blue;
Color[k].green = rainbow[9].green;
if (!XAllocColor(h_display,Map,&Color[k])) ColorError();
}
else if (fullColor == 0 && GotGreyMap++ ==0)
{
int i;
Map = DefaultColormapOfScreen(h_screen);
for (i=0; i<=90; i++)
{
int color = 65535-i*65535/90;
Grey[i].red = color;
Grey[i].blue = color;
Grey[i].green = color;
if (!XAllocColor(h_display,Map,&Grey[i])) ColorError();
}
}
if (fullColor == 0) ColorsUsed = Grey;
else ColorsUsed = Color;
XSetForeground(h_display,temp_gc,ColorsUsed[0].pixel);
XFillRectangle(h_display,h_drawable,temp_gc,xx,YScale(Limit.ymax),
(XScale(Limit.xmax)-xx),(yy-YScale(Limit.ymax)));
for (i=0; i<nXBins; i++)
{
x += xBinWidth;
ww = XScale(x) - xx;
for (j=0; j<nYBins; j++)
{
int color = scale * (*bins++ - minBin);
y += yBinWidth;
hh = yy - YScale(y);
yy -= hh;
if (color==0) continue;
XSetForeground(h_display,temp_gc,ColorsUsed[color].pixel);
XFillRectangle(h_display,h_drawable,temp_gc,xx,yy,ww,hh);
}
xx += ww;
yy = YScale(Limit.ymin);
y = Limit.ymin;
}
XFreeGC(h_display,temp_gc);
}
void drawLego2D_X11(display disp)
{
float angle = 45; /* degrees */
float sin45 = 1./sqrt(2.);
float cos45 = sin45;
float xBinWidth = (Limit.xmax - Limit.xmin)/disp->bins.xAxis.nBins;
float yBinWidth = cos45*(Limit.ymax - Limit.ymin)/disp->bins.yAxis.nBins;
float x = Limit.xmax;
float y = Limit.ymax;
float scale = (YScale(Limit.ymax) - YScale(Limit.ymin)) * ( 1 - cos45 )
/ (disp->bins.binMax - disp->bins.binMin);
int i,j;
int xx = XScale(Limit.xmax);
int yy = YScale(Limit.ymax);
int ww, hh, oo, xxx, yyy;
XPoint points[5];
static XColor bright, medium, dark;
static int GotColors = 0;
static Pixmap Medium;
static int GotPixmap = 0;
GC bright_gc, medium_gc, dark_gc;
bright_gc = XCreateGC(h_display,h_drawable,0,NULL);
medium_gc = XCreateGC(h_display,h_drawable,0,NULL);
dark_gc = XCreateGC(h_display,h_drawable,0,NULL);
if (h_color && GotColors++ == 0)
{
Colormap Map = DefaultColormapOfScreen(h_screen);
bright.red = 55000;
bright.blue = 55000;
bright.green = 55000;
if (!XAllocColor(h_display,Map,&bright)) ColorError();
medium.red = 35000;
medium.blue = 35000;
medium.green = 35000;
if (!XAllocColor(h_display,Map,&medium)) ColorError();
dark.red = 10000;
dark.blue = 10000;
dark.green = 10000;
if (!XAllocColor(h_display,Map,&dark)) ColorError();
}
else if (!h_color && GotPixmap++ == 0)
{
static char medium_data[] = {0x02, 0x01};
Medium = XCreatePixmapFromBitmapData(h_display,h_drawable,
medium_data,2,2,0,1,1);
}
if (h_color)
{
XSetForeground(h_display,medium_gc,medium.pixel);
XSetForeground(h_display,bright_gc,bright.pixel);
XSetForeground(h_display,dark_gc ,dark.pixel);
}
else
{
XSetFillStyle(h_display,medium_gc,FillOpaqueStippled);
XSetStipple(h_display,medium_gc,Medium);
XSetForeground(h_display,bright_gc,WhitePixelOfScreen(h_screen));
XSetForeground(h_display,medium_gc,WhitePixelOfScreen(h_screen));
XSetForeground(h_display,dark_gc ,BlackPixelOfScreen(h_screen));
XSetBackground(h_display,medium_gc,BlackPixelOfScreen(h_screen));
}
points[0].x = xx - (YScale(Limit.ymin) - YScale(Limit.ymax))*cos45;
points[0].y = yy + (YScale(Limit.ymin) - YScale(Limit.ymax))*(1-sin45);
points[1].x = XScale(Limit.xmin) - (YScale(Limit.ymin) -
YScale(Limit.ymax))*cos45;
points[1].y = yy + (YScale(Limit.ymin) - YScale(Limit.ymax))*(1-sin45);
points[2].x = XScale(Limit.xmin);
points[2].y = YScale(Limit.ymin);
points[3].x = xx;
points[3].y = YScale(Limit.ymin);
points[4].x = xx - (YScale(Limit.ymin) - YScale(Limit.ymax))*cos45;
points[4].y = yy + (YScale(Limit.ymin) - YScale(Limit.ymax))*(1-sin45);
XFillPolygon(h_display,h_drawable,medium_gc,points,5,
Convex,CoordModeOrigin);
xxx = -(YScale(Limit.ymin) - YScale(Limit.ymax))*cos45;
yyy = (YScale(Limit.ymin) - YScale(Limit.ymax))*(1-sin45);
for (j=0; j<disp->bins.yAxis.nBins; j++)
{
y -= yBinWidth;
hh = cos45*(YScale(y) - yy);
oo = sin45*(yy - YScale(y));
yy += hh;
disp->bins.data += disp->bins.xAxis.nBins*disp->bins.yAxis.nBins - 1;
for (i=0; i<disp->bins.xAxis.nBins; i++)
{
int size = scale * (*disp->bins.data - disp->bins.binMin);
disp->bins.data -= disp->bins.yAxis.nBins;
x -= xBinWidth;
ww = xx - XScale(x);
xx -= ww;
if (size == 0) continue;
points[0].x = xx + xxx;
points[0].y = yy + yyy + size;
points[1].x = xx + xxx + ww;
points[1].y = yy + yyy + size;
points[2].x = xx + xxx + ww + oo;
points[2].y = yy + yyy - hh + size;
points[3].x = xx + xxx + oo;
points[3].y = yy + yyy - hh + size;
points[4].x = xx + xxx;
points[4].y = yy + yyy + size;
XFillPolygon(h_display,h_drawable,medium_gc,points,5,
Convex,CoordModeOrigin);
points[0].x = xx + xxx;
points[0].y = yy + yyy;
points[1].x = xx + xxx;
points[1].y = yy + yyy + size;
points[2].x = xx + xxx + oo;
points[2].y = yy + yyy - hh + size;
points[3].x = xx + xxx + oo;
points[3].y = yy + yyy - hh;
points[4].x = xx + xxx;
points[4].y = yy + yyy;
XFillPolygon(h_display,h_drawable,bright_gc,points,5,
Convex,CoordModeOrigin);
points[0].x = xx + xxx;
points[0].y = yy + yyy;
points[1].x = xx + xxx + ww;
points[1].y = yy + yyy;
points[2].x = xx + xxx + ww;
points[2].y = yy + yyy + size;
points[3].x = xx + xxx;
points[3].y = yy + yyy + size;
points[4].x = xx + xxx;
points[4].y = yy + yyy;
XFillPolygon(h_display,h_drawable,dark_gc,points,5,
Convex,CoordModeOrigin);
}
xxx -= oo;
xx = XScale(Limit.xmax);
x = Limit.xmax;
}
XFreeGC(h_display,bright_gc);
XFreeGC(h_display,dark_gc);
XFreeGC(h_display,medium_gc);
}
void drawScatter3D_X11(display disp, float *coords, int nCoords)
{
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.