/* $OpenXM: OpenXM_contrib2/asir2000/plot/smoothing.c,v 1.3 2000/10/24 01:53:53 takayama Exp $ */ #include "ca.h" #include "parse.h" #include "ox.h" #include "ifplot.h" #include "cursor.h" #define MAG 1 #define PRINT_XOFFSET 100 #define PRINT_YOFFSET 100 struct polyLine { int numberOfSegments; int limit; int *x; int *y; }; static FILE *Fp = NULL; static void *gcmalloc(int a); static struct polyLine *polyLine_new(void); static struct polyLine *polyLine_addNewSegment(struct polyLine *pl, int x,int y); static int polyLine_lastY(struct polyLine *pl); static void polyLine_outputPS(struct polyLine *pl); static void polyLine_output_bezier_PS(struct polyLine *pl); static void polyLine_outputProlog(int xmin, int ymin, int xmax, int ymax); static void polyLine_outputEpilog(void); static void polyLine_error(char *s); #define translateX(x) (x*MAG+PRINT_XOFFSET) #define translateY(y) (y*MAG+PRINT_YOFFSET) /* #define translateY(y) ((Ysize-y)*MAG+PRINT_YOFFSET) */ #define IS_DOT != 0 #define IS_POLYLINE > -1 #define YES 1 #define NO 0 static int Xsize = 0; static int Ysize = 0; static int updatePolyLine(struct polyLine *pl[], int plSize, int prev[], int Curr[], int x); static void polyLine_outputPS_dashed_line(int x0,int y0,int x1,int y1); static int polyLine_pline(struct canvas *can); static void *gcmalloc(a) { void *m; /* BUG: interruption must be locked. */ m = (void *) GC_malloc(a); if (m == NULL) polyLine_error("no memory"); return(m); } #define MINIMAL_POLYLINE_SIZE 10 static struct polyLine *polyLine_new_with_size(int size) { struct polyLine *pl; pl = (struct polyLine *)gcmalloc(sizeof(struct polyLine)); pl-> limit = (size > 0? size: 1); pl-> numberOfSegments = 0; pl->x = (int *)gcmalloc(sizeof(int)*(pl->limit)); pl->y = (int *)gcmalloc(sizeof(int)*(pl->limit)); return(pl); } static struct polyLine *polyLine_new(void) { return( polyLine_new_with_size(MINIMAL_POLYLINE_SIZE)); } static struct polyLine *polyLine_addNewSegment(struct polyLine *pl, int x,int y) { int n,limit,i; struct polyLine *new_pl; limit = pl->limit; n = pl->numberOfSegments; if (n >= limit) { new_pl = polyLine_new_with_size( 2*limit ); new_pl -> numberOfSegments = pl->numberOfSegments; for (i=0; inumberOfSegments; i++) { new_pl->x[i] = pl->x[i]; new_pl->y[i] = pl->y[i]; } pl = new_pl; } pl->numberOfSegments++; pl->x[n] = x; pl->y[n] = y; return(pl); } static int polyLine_lastY(struct polyLine *pl) { int n; n = pl->numberOfSegments; if (n == 0) { polyLine_error("polyLine_lastY: empty polyLine."); } return(pl->y[n-1]); } static void polyLine_outputPS(struct polyLine *pl) { int n,i; n = pl->numberOfSegments; if (n == 1) { fprintf(Fp," %d %d ifplot_putpixel\n",translateX(pl->x[0]),translateY(pl->y[0])); }else if (n > 1) { fprintf(Fp," newpath "); for (i=0; ix[i]),translateY(pl->y[i])); if (i==0) fprintf(Fp," moveto "); else fprintf(Fp," lineto "); } fprintf(Fp," stroke\n"); } fflush(Fp); } static void polyLine_output_bezier_PS(struct polyLine *pl) { int n,i,m; n = pl->numberOfSegments; if (n == 1) { fprintf(Fp," %d %d ifplot_putpixel\n",translateX(pl->x[0]),translateY(pl->y[0])); }else if (n > 1) { fprintf(Fp," newpath "); i=0; m = n-1-((n-1)/3)*3; fprintf(Fp," %d %d ",translateX(pl->x[i]),translateY(pl->y[i])); fprintf(Fp," moveto \n "); for (i=1; i<= ((n-1)/3)*3; i++) { fprintf(Fp," %d %d ",translateX(pl->x[i]),translateY(pl->y[i])); if ( i%3 == 0) fprintf(Fp," curveto "); } for (i=n-m; ix[i]),translateY(pl->y[i])); } fprintf(Fp," stroke\n"); } fflush(Fp); } static void polyLine_outputProlog(int xmin, int ymin,int xmax, int ymax) { fprintf(Fp,"%%!PS-Adobe-1.0\n"); fprintf(Fp,"%%%%BoundingBox: %d %d %d %d \n", PRINT_XOFFSET+xmin*MAG,PRINT_YOFFSET+ymin*MAG, PRINT_XOFFSET+xmax*MAG, PRINT_YOFFSET+ymax*MAG); fprintf(Fp,"%%%%Creator: This is generated by ifplot\n"); fprintf(Fp,"%%%%Title: ifplot\n"); fprintf(Fp,"%%%%EndComments: \n"); fprintf(Fp,"0.1 setlinewidth \n"); fprintf(Fp,"2 setlinecap \n"); fprintf(Fp,"2 setlinejoin \n"); fprintf(Fp,"/ifplot_putpixel { \n"); fprintf(Fp," /yyy 2 1 roll def /xxx 2 1 roll def \n"); fprintf(Fp," gsave newpath xxx yyy .5 0 360 arc \n"); fprintf(Fp," fill grestore \n"); fprintf(Fp,"} def \n"); fflush(Fp); } static void polyLine_outputEpilog(void) { fprintf(Fp,"showpage \n"); fflush(Fp); } static void polyLine_error(char *s) { fprintf(stderr,"Error in smoothing: %s\n",s); exit(-1); } static int updatePolyLine(struct polyLine *pl[], int plSize, int prev[], int curr[],int x) { /* 1 <= y <= Ysize , curr[0], curr[Ysize+1] = 0 , i=y . prev = {-1, -1, -1, 0, 1, -1, 2, -1} -1: no polyLine. 0:pl[0], 1:pl[1], curr = {0, 1, 0, 1, 1, 1, 0, 0} 0: no dot, 1: dot. */ /* Return Value: plSize, pl, prev */ int i; static int *prevHasNext = NULL; static struct polyLine **tmpPl = NULL; static struct polyLine **newPl = NULL; int tmpPlSize = 0; static int *tmpPrev = NULL; int newPlSize = 0; extern int Ysize; if (prevHasNext == NULL) prevHasNext = (int *)gcmalloc(sizeof(int)*(Ysize+2)); if (tmpPl == NULL) tmpPl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2)); if (newPl == NULL) newPl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2)); if (tmpPrev == NULL) tmpPrev = (int *)gcmalloc(sizeof(int)*(Ysize+2)); for (i=0; inoaxis ) return; xadj = yadj = 0; if ( (can->xmin < 0) && (can->xmax > 0) ) { x0 = (int)((can->width-1)*(-can->xmin/(can->xmax-can->xmin))); polyLine_outputPS_dashed_line(translateX(x0),translateY(0), translateX(x0),translateY(can->height)); } else if ( can->xmin >= 0 ) x0 = 0; else x0 = can->width-1-D; if ( (can->ymin < 0) && (can->ymax > 0) ) { y0 = (int)((can->height-1)*(can->ymax/(can->ymax-can->ymin))); polyLine_outputPS_dashed_line(translateX(0),translateY(y0), translateX(can->width),translateY(y0)); } else if ( can->ymin >= 0 ) y0 = can->height-1; else y0 = D; /* BUG: not written yet a code for PS. w = can->xmax-can->xmin; w1 = w * DEFAULTWIDTH/can->width; e = adjust_scale(EXP10(floor(log10(w1))),w1); for ( n = ceil(can->xmin/e); n*e<= can->xmax; n++ ) { x = (int)can->width*(n*e-can->xmin)/w; DRAWLINE(display,d,drawGC,x,y0,x,y0-D); sprintf(buf,"%g",n*e); DRAWSTRING(display,d,scaleGC,x+2,y0,buf,strlen(buf)); } w = can->ymax-can->ymin; w1 = w * DEFAULTHEIGHT/can->height; e = adjust_scale(EXP10(floor(log10(w1))),w1); for ( n = ceil(can->ymin/e); n*e<= can->ymax; n++ ) { y = (int)can->height*(1-(n*e-can->ymin)/w); DRAWLINE(display,d,drawGC,x0,y,x0+D,y); sprintf(buf,"%g",n*e); if ( can->xmax <= 0 ) xadj = TEXTWIDTH(sffs,buf,strlen(buf)); DRAWSTRING(display,d,scaleGC,x0-xadj,y,buf,strlen(buf)); } */ } generatePS_from_image(FILE *fp,XImage *image,int xsize, int ysize, int color[],int colorSize, struct canvas *can) { struct polyLine **pl; int plSize = 0; int *prev; int *curr; int i,x,y,c; Xsize = xsize; Ysize = ysize; pl = (struct polyLine **)gcmalloc(sizeof(struct polyLine *)*(Ysize+2)); prev = (int *)gcmalloc(sizeof(int)*(Ysize+2)); curr = (int *)gcmalloc(sizeof(int)*(Ysize+2)); Fp = fp; polyLine_outputProlog(0,0,Xsize,Ysize); for (c=0; c