/* * $Source: /tmp_mnt/n/fs/grad1/jsp/src/jgraph/RCS/draw.c,v $ * $Revision: 8.3 $ * $Date: 92/11/30 11:42:10 $ * $Author: jsp $ */ #include "jgraph.h" #include #include #include //by pzn@debian.org #include //by pzn@debian.org static char real_eof = EOF; float ctop(val, axis) float val; Axis axis; { if (axis->is_lg) { if (val <= 0.0) { error_header(); fprintf(stderr, "Value of %f is at negative infinity with logrhythmic %c axis\n", val, (axis->is_x) ? 'x' : 'y'); exit(1); } return (log(val) / axis->logfactor - axis->logmin) * axis->factor; } else { return (val - axis->min) * axis->factor; } } float disttop(val, axis) float val; Axis axis; { if (axis->is_lg) { return FCPI * val; } else { return (val) * axis->factor; } } float intop(val) float val; { return FCPI * val; } #define MAXIMUM(a,b) ((a > b) ? a : b) draw_axis(a, other) Axis a, other; { char orientation; Hash h; String s; orientation = (a->is_x) ? 'x' : 'y'; setlinewidth(1.0); comment("Drawing Axis"); if (a->grid_lines) { comment("Drawing Grid lines"); gsave(); setgray(a->gr_graytype, a->gr_gray); for (h = first(a->hash_lines); h != nil(a->hash_lines); h = next(h)) { if (h->major) { printline(h->loc, 0.0, h->loc, other->psize, orientation); } } grestore(); } if (a->mgrid_lines) { comment("Drawing Minor Grid lines"); gsave(); setgray(a->mgr_graytype, a->mgr_gray); for (h = first(a->hash_lines); h != nil(a->hash_lines); h = next(h)) { if (!h->major) { printline(h->loc, 0.0, h->loc, other->psize, orientation); } } grestore(); } gsave(); setgray(a->graytype, a->gray); if (a->draw_axis_line) { printline(0.0, a->draw_at, a->psize, a->draw_at, orientation); } if (a->draw_hash_marks) { comment("Drawing Hash Marks"); for (h = first(a->hash_lines); h != nil(a->hash_lines); h = next(h)) { printline(h->loc, a->draw_hash_marks_at, h->loc, a->draw_hash_marks_at + (h->size * a->hash_scale), orientation); } } if (a->draw_hash_labels) { comment("Drawing Hash Labels"); for (s = first(a->hash_labels); s != nil(a->hash_labels); s = next(s)) { a->hl->label = s->s->label; if (a->is_x) { a->hl->x = s->s->x; } else { a->hl->y = s->s->y; } draw_label(a->hl); } } if (a->draw_axis_label) { comment("Drawing Axis Label"); draw_label(a->label); } grestore(); printf("\n"); } draw_label(l) Label l; { if (l->label == CNULL) return; comment(l->label); print_label(l); } set_clip(g) Graph g; { comment("Setting Clip"); printf("newpath\n"); printf(" 0 0 moveto 0 %f lineto %f %f lineto %f 0 lineto\n", g->y_axis->psize, g->x_axis->psize, g->y_axis->psize, g->x_axis->psize); printf(" closepath clip newpath\n"); } draw_curves(g) Graph g; { Curve c; gsave(); printf("\n"); if (g->clip) set_clip(g); for(c = first(g->curves); c != nil(g->curves); c = next(c)) { draw_curve(c, g); } grestore(); printf("\n"); } draw_curve(c, g) Curve c; Graph g; { Point p, px, py; int i, j; float this_x, this_y, last_x, last_y, x, y; gsave(); setgray(c->graytype, c->gray); if (c->clip) set_clip(g); if (first(c->xepts) != nil(c->xepts) || first(c->yepts) != nil(c->yepts)) { comment("Drawing Epts"); px = first(c->xepts); py = first(c->yepts); setlinewidth(c->linethick); setlinestyle('s', (Flist)0); for (p = first(c->pts); p != nil(c->pts); p = next(p)) { if (p->e == 'x') { x = ctop(p->x, g->x_axis); y = ctop(p->y, g->y_axis); print_ebar(x, y, ctop(px->x, g->x_axis), c->marksize[1]/2.0, 'x'); px = next(px); print_ebar(x, y, ctop(px->x, g->x_axis), c->marksize[1]/2.0, 'x'); px = next(px); } else if (p->e == 'y') { x = ctop(p->x, g->x_axis); y = ctop(p->y, g->y_axis); print_ebar(y, x, ctop(py->y, g->y_axis), c->marksize[0]/2.0, 'y'); py = next(py); print_ebar(y, x, ctop(py->y, g->y_axis), c->marksize[0]/2.0, 'y'); py = next(py); } } } comment("Drawing Curve"); if (c->linetype != '0' || c->poly) { if (c->bezier) { i = 0; j = 0; if (c->poly) printf("newpath "); for (p = first(c->pts); p != nil(c->pts); p = next(p)) { if (j == 0 && i == 0) { start_line(ctop(p->x, g->x_axis), ctop(p->y, g->y_axis), c); j++; } else if (i != 0) { bezier_control(ctop(p->x, g->x_axis), ctop(p->y, g->y_axis)); } else { bezier_end(ctop(p->x, g->x_axis), ctop(p->y, g->y_axis)); j++; } if (!c->poly && j == 30 && i == 0) { end_line(); p = prev(p); j = 0; i = 0; } else i = (i + 1) % 3; } if (j != 0) { if (c->poly) { printf("closepath "); setfill(0.0, 0.0, c->pfilltype, c->pfill, c->ppattern, c->pparg); } end_line(); } } else { i = 0; if (c->poly) printf("newpath "); for (p = first(c->pts); p != nil(c->pts); p = next(p)) { if (i == 0) { start_line(ctop(p->x, g->x_axis), ctop(p->y, g->y_axis), c); } else { cont_line(ctop(p->x, g->x_axis), ctop(p->y, g->y_axis)); } if (!c->poly && i == 100 && next(p)) { end_line(); p = prev(p); i = 0; } else i++; } if (i != 0) { if (c->poly) { printf("closepath "); setfill(0.0, 0.0, c->pfilltype, c->pfill, c->ppattern, c->pparg); } end_line(); } } } comment("Drawing Curve points"); i = 0; for (p = first(c->pts); p != nil(c->pts); p = next(p)) { this_x = ctop(p->x, g->x_axis); this_y = ctop(p->y, g->y_axis); if (!c->bezier || i == 0) draw_mark(this_x, this_y, c, g); if (p != first(c->pts)) { if (c->rarrows || (c->rarrow && p == last(c->pts))) { if (!c->bezier || i == 0) draw_arrow(this_x, this_y, last_x, last_y, c); } if (c->larrows || (c->larrow && prev(p) == first(c->pts))) { if (!c->bezier || i == 1) draw_arrow(last_x, last_y, this_x, this_y, c); } } last_x = this_x; last_y = this_y; i = (i + 1) % 3; } grestore(); printf("\n"); } draw_mark(x, y, c, g) float x, y; Curve c; Graph g; { Point p; float ms0, ms1, scx, scy, trx, try; int i, j; FILE *f; char ch; int done, newline; char inp[100]; int bb[4]; if (c->marktype == 'n') return; ms0 = c->marksize[0] / 2.0; ms1 = c->marksize[1] / 2.0; gsave(); printf(" %f %f translate %f rotate\n", x, y, c->mrotate); switch (c->marktype) { case 'n': break; case 'E': if (c->eps == CNULL) break; f = fopen(c->eps, "r"); if (f == NULL) { fprintf(stderr, "Error: eps file %s couldn't be opened\n", c->eps); exit(1); } /* Get bbox */ newline = 1; done = 0; while(!done) { while(!newline) { ch = getc(f); if (ch == real_eof) { fprintf(stderr, "Error: Eps file '%s' has %s\n", c->eps, "no bounding box"); exit(1); } newline = (ch == '\n'); } fscanf(f, "%s", inp); if (strcmp(inp, "%%BoundingBox:") == 0) done = 1; } for (i = 0; i < 4; i++) { if (fscanf(f, "%d", &(bb[i])) == NULL) { fprintf(stderr, "Error: Eps file '%s': eof in %s\n", c->eps, "bounding box"); exit(1); } } if (bb[2] - bb[0] == 0) { scx = ms0; trx = 0.0; } else { scx = ms0 * 2.0/(float)(bb[2] - bb[0]); trx = -(float)(bb[2] - bb[0])/2.0 - bb[0]; } if (bb[3] - bb[1] == 0) { scy = ms1; try = 0.0; } else { scy = ms1 * 2.0/(float)(bb[3] - bb[1]); try = -(float)(bb[3] - bb[1])/2.0 - bb[1]; } /* Don't scale if ms == 0 0 */ if (ms0 == 0.0 && ms1 == 0.0) { scx = 1.0; scy = 1.0; } sprintf(inp, "Including eps file %s", c->eps); comment(inp); /* Use bbox to scale and translate */ printf("%f %f scale %f %f translate\n", scx, scy, trx, try); /* Include the rest of the file */ for (ch = getc(f); ch != real_eof; ch = getc(f)) putchar(ch); putchar('\n'); fclose(f); break; case 'p': if (c->postscript == CNULL) break; if (ms0 != 0.0 || ms1 != 0.0) { printf("%f %f scale\n", ms0, ms1); } if (!c->postfile) { printf("%s\n", c->postscript); } else { f = fopen(c->postscript, "r"); if (f == NULL) { fprintf(stderr, "Error: postscript file %s couldn't be opened\n", c->postscript); exit(1); } for (ch = getc(f); ch != real_eof; ch = getc(f)) putchar(ch); putchar('\n'); fclose(f); } break; case 'c': printline(-ms0, 0.0, ms0, 0.0, 'x'); printline(-ms1, 0.0, ms1, 0.0, 'y'); break; case 'b': start_poly(-ms0, -ms1); cont_poly(ms0, -ms1); cont_poly(ms0, ms1); cont_poly(-ms0, ms1); end_poly(x, y, c->filltype, c->fill, c->pattern, c->parg); break; case 'd': start_poly(-ms0, 0.0); cont_poly(0.0, -ms1); cont_poly(ms0, 0.0); cont_poly(0.0, ms1); end_poly(x, y, c->filltype, c->fill, c->pattern, c->parg); break; case 'g': p = first(c->general_marks); if (p == nil(c->general_marks)) break; if (next(p) == nil(c->general_marks)) break; start_poly(p->x*ms0, p->y*ms1); for(p = next(p); p != nil(c->general_marks); p = next(p)) cont_poly(p->x*ms0, p->y*ms1); end_poly(x, y, c->filltype, c->fill, c->pattern, c->parg); break; case 'G': i = 0; for (p = first(c->general_marks); p != nil(c->general_marks); p = next(p)) { if (i == 0) { printf("%f %f moveto ", p->x*ms0, p->y*ms1); } else { printf("%f %f lineto\n", p->x*ms0, p->y*ms1); } if (i == 100) { printf("stroke\n"); p = prev(p); i = 0; } else i++; } if (i != 0) printf("stroke\n"); break; case 'B': i = 0; j = 0; for (p = first(c->general_marks); p != nil(c->general_marks); p = next(p)) { if (j == 0 && i == 0) { printf("%f %f moveto ", p->x*ms0, p->y*ms1); j++; } else if (i != 0) { printf("%f %f ", p->x*ms0, p->y*ms1); } else { printf("%f %f curveto\n", p->x*ms0, p->y*ms1); j++; } if (j == 30 && i == 0) { printf(" stroke\n"); p = prev(p); j = 0; i = 0; } else i = (i + 1) % 3; } if (j != 0) printf(" stroke\n"); if (! ((i == 1) || (i == 0 && j == 0))) { fprintf(stderr, "Error: curve %d, %s\n", c->num, "wrong number of points for bezier marktype\n"); exit(1); } break; case 'Z': i = 0; j = 0; for (p = first(c->general_marks); p != nil(c->general_marks); p = next(p)) { if (i == 0 && j == 0) { printf("newpath %f %f moveto ", p->x*ms0, p->y*ms1); j++; } else if (i != 0) { printf("%f %f ", p->x*ms0, p->y*ms1); } else { printf("%f %f curveto\n", p->x*ms0, p->y*ms1); } i = (i + 1) % 3; } printf("closepath "); setfill(x, y, c->filltype, c->fill, c->pattern, c->parg); printf("stroke\n"); if (i != 1) { fprintf(stderr, "Error: curve %d, %s\n", c->num, "wrong number of points for bezier marktype\n"); exit(1); } break; case 'x': printline(-ms0, -ms1, ms0, ms1, 'x'); printline(-ms0, ms1, ms0, -ms1, 'x'); break; case 'o': printellipse(x, y, ms0, ms0, c->filltype, c->fill, c->pattern, c->parg); break; case 'e': printellipse(x, y, ms0, ms1, c->filltype, c->fill, c->pattern, c->parg); break; case 't': start_poly(ms0, -ms1); cont_poly(0.0, ms1); cont_poly(-ms0, -ms1); end_poly(x, y, c->filltype, c->fill, c->pattern, c->parg); break; case 'X': start_poly(ms0, 0.0); cont_poly(-ms0, 0.0); cont_poly(-ms0, g->x_axis->draw_at - y); cont_poly(ms0, g->x_axis->draw_at - y); end_poly(x, y, c->filltype, c->fill, c->pattern, c->parg); break; case 'Y': start_poly(0.0, ms1); cont_poly(0.0, -ms1); cont_poly(g->y_axis->draw_at - x, -ms1); cont_poly(g->y_axis->draw_at - x, ms1); end_poly(x, y, c->filltype, c->fill, c->pattern, c->parg); break; case 'l': draw_label(c->lmark); break; default: error_header(); fprintf(stderr, "Unknown mark: %c\n", c->marktype); break; } grestore(); } draw_arrow(x1, y1, x2, y2, c) float x1, y1, x2, y2; Curve c; { float dx, dy; float ms0; float theta, ct, st; if (c->marktype == 'o') { dx = x1 - x2; dy = y1 - y2; if (dx == 0.0 && dy == 0.0) return; ms0 = c->marksize[0] / 2.0; if (dx == 0.0) theta = asin(1.0); else theta = atan(dy/dx); if (theta < 0.0) theta = -theta; ct = cos(theta)*ms0; st = sin(theta)*ms0; x1 = x1 + ct*(dx > 0.0 ? -1.0 : 1.0); y1 = y1 + st*(dy > 0.0 ? -1.0 : 1.0); if ( ((x1 - x2 > 0) != (dx > 0)) || ((y1 - y2 > 0) != (dy > 0)) ) return; } dx = x1 - x2; dy = y1 - y2; if (dx == 0.0 && dy == 0.0) return; gsave(); printf("%f %f translate %f %f atan rotate\n", x1, y1, dy, dx); start_poly(0.0, 0.0); cont_poly(-(c->asize[0]), (c->asize[1])); cont_poly(-(c->asize[0]), -(c->asize[1])); end_poly(0.0, 0.0, c->afilltype, c->afill, c->apattern, c->aparg); grestore(); printf("\n"); } draw_legend(g) Graph g; { Curve c; Legend l; float x, y; char tmpmktype; l = g->legend; comment("Drawing legend"); if (l->type == 'n' || l->anylines < 0) return; gsave(); if (l->type == 'u') { printf("%f %f translate %f rotate\n", l->l->x, l->l->y, l->l->rotate); } for (c = first(g->curves); c != nil(g->curves); c = next(c)) { if (c->l->label != CNULL) { gsave(); setgray(c->graytype, c->gray); y = (c->l->ymax + c->l->ymin) / 2.0; if (l->anylines) { if (c->linetype != '0' && l->linelength != 0) { if (l->type == 'c' && c->l->hj == 'r') { x = c->l->x + l->midspace; } else { x = c->l->x - l->midspace - l->linelength; } start_line(x, y, c); cont_line(x+l->linelength, y); end_line(); } tmpmktype = c->marktype; c->marktype = 'n'; if (c->larrows || c->larrow) draw_arrow(x, y, x+l->linelength, y, c); if (c->rarrows || c->rarrow) draw_arrow(x+l->linelength, y, x, y, c); c->marktype = tmpmktype; if (l->type == 'c' && c->l->hj == 'r') { x = c->l->x + l->midspace + l->linelength / 2.0; } else { x = c->l->x - l->midspace - l->linelength / 2.0; } } else if (l->type == 'c' && c->l->hj == 'r') { x = c->l->x + l->midspace; } else { x = c->l->x - l->midspace; } if (c->marktype == 'X' || c->marktype == 'Y') { char old; old = c->marktype; c->marktype = 'b'; draw_mark(x, y, c, g); c->marktype = old; } else { draw_mark(x, y, c, g); } grestore(); printf("\n"); draw_label(c->l); } } grestore(); printf("\n"); } draw_strings(g) Graph g; { String s; comment("Drawing strings"); for (s = first(g->strings); s != nil(g->strings); s = next(s)) draw_label(s->s); } draw_graph(g) Graph g; { comment("Drawing New Graph"); printf("%f %f translate\n", g->x_translate, g->y_translate); if (g->border) { printline(0.0, 0.0, 0.0, g->y_axis->psize, 'x'); printline(0.0, 0.0, 0.0, g->x_axis->psize, 'y'); printline(g->x_axis->psize, 0.0, g->x_axis->psize, g->y_axis->psize, 'x'); printline(g->y_axis->psize, 0.0, g->y_axis->psize, g->x_axis->psize, 'y'); } draw_axis(g->x_axis, g->y_axis); draw_axis(g->y_axis, g->x_axis); draw_label(g->title); draw_curves(g); draw_legend(g); draw_strings(g); printf("%f %f translate\n", - g->x_translate, - g->y_translate); } draw_graphs(gs, pp, landscape) Graphs gs; int pp; int landscape; { Graphs gs_p; Graph g; int page_counter=0; for (gs_p = first(gs); gs_p != nil(gs); gs_p = next(gs_p)) { page_counter++; draw_header(gs_p, pp, landscape); for (g = first(gs_p->g); g != nil(gs_p->g); g = next(g)) { draw_graph(g); } draw_footer(gs_p, pp); } if (pp) { printf("\n%%%%Trailer\n"); printf("%%%%Pages: %i\n",page_counter); printf("%%%%EOF\n"); } } draw_header(gs, pp, landscape) Graphs gs; int pp; int landscape; { FILE *f; char c; if (gs->page == 1) { if (pp) { printf("%%!PS-Adobe-3.0\n"); printf("%%%%Pages: (atend)\n"); printf("%%%%Creator: jgraph\n"); printf("%%%%EndComments\n\n"); printf("%%%%BeginProlog\n"); printf("%%%%EndProlog\n"); printf("%%%%BeginSetup\n"); printf("%%%%EndSetup\n"); } else { printf("%%!PS-Adobe-2.0 EPSF-1.2\n"); printf("%%%%Creator: jgraph\n"); } } if (pp) { printf("\n%%%%Page: %d %d\n", gs->page, gs->page); printf("%%%%BeginPageSetup\n"); printf("%%%%EndPageSetup\n\n"); } if ( (gs->page>1) && !pp ) { /* tring EPS with more than one page */ fprintf(stderr, "Error: 'newpage' token is not allowed" " without '-P' command line option.\n"); exit(1); } /* if (landscape) { printf("%%%%BoundingBox: %d %d %d %d\n", gs->bb[1], gs->bb[0], gs->bb[3], gs->bb[2]); } else { printf("%%%%BoundingBox: %d %d %d %d\n", gs->bb[0], gs->bb[1], gs->bb[2], gs->bb[3]); } printf("%%%%EndComments\n"); */ //BEGIN added by pzn@debian.org { // expands the bounding box to fit characters with tilde, acute,... // if user has set JGRAPH_BORDER enviroment variable int expandborder=0; char *s; \ s=(char *)getenv("JGRAPH_BORDER"); if (s!=NULL) { expandborder=atoi(s); } if (!pp) { if (landscape) { printf("%%%%BoundingBox: %d %d %d %d\n", gs->bb[1]-expandborder, gs->bb[0]-expandborder, gs->bb[3]+expandborder, gs->bb[2]+expandborder); } else { printf("%%%%BoundingBox: %d %d %d %d\n", gs->bb[0]-expandborder, gs->bb[1]-expandborder, gs->bb[2]+expandborder, gs->bb[3]+expandborder); } printf("%%%%EndComments\n\n"); } } if (gs->page==1) //reencode fonts to ISOLatin1 or other { //NOTE: this is a preliminary version. It will only work with // the default fonts, that are Times-Roman and Times-Bold // "export JGRAPH_ENCODING=ISOLatin1Encoding" will work in sh char *s; \ s=(char *)getenv("JGRAPH_ENCODING"); if ((s!=NULL) && (strlen(s)>0)) { comment("Setting font encoding by pzn@debian.org"); printf("/Times-Bold findfont\n"); printf("dup length dict begin\n"); printf(" {1 index /FID ne {def} {pop pop} ifelse} forall\n"); printf(" /Encoding %s def\n",s); printf(" currentdict\n"); printf("end\n"); printf("/Times-Bold exch definefont pop\n"); printf("/Times-Roman findfont\n"); printf("dup length dict begin\n"); printf(" {1 index /FID ne {def} {pop pop} ifelse} forall\n"); printf(" /Encoding %s def\n",s); printf(" currentdict\n"); printf("end\n"); printf("/Times-Roman exch definefont pop\n"); comment("End of font encoding"); printf("\n"); } } //END added by pzn if (landscape) { printf("-90 rotate\n"); } if (pp) { if (landscape) { printf("%f 0 translate\n", -(11.0 * FCPI)); printf("%f %f translate\n", (((11.0 * FCPI) - (gs->bb[2] - gs->bb[0])) / 2.0) - gs->bb[0], (((8.5 * FCPI) - (gs->bb[3] - gs->bb[1])) / 2.0) - gs->bb[1]); } else { printf("%f %f translate\n", (((8.5 * FCPI) - (gs->bb[2] - gs->bb[0])) / 2.0) - gs->bb[0], (((11.0 * FCPI) - (gs->bb[3] - gs->bb[1])) / 2.0) - gs->bb[1]); } } else if (landscape) { printf("%f 0 translate\n", -gs->bb[2] - gs->bb[0]); } printf("1 setlinecap 1 setlinejoin\n"); printf("0.700 setlinewidth\n"); printf("0.00 setgray\n"); printf("\n"); printf("/Jrnd { exch cvi exch cvi dup 3 1 roll idiv mul } def\n"); printf("/JDEdict 8 dict def\n"); printf("JDEdict /mtrx matrix put\n"); printf("/JDE {\n"); printf(" JDEdict begin\n"); printf(" /yrad exch def\n"); printf(" /xrad exch def\n"); printf(" /savematrix mtrx currentmatrix def\n"); printf(" xrad yrad scale\n"); printf(" 0 0 1 0 360 arc\n"); printf(" savematrix setmatrix\n"); printf(" end\n"); printf("} def\n"); printf("/JSTR {\n"); printf(" gsave 1 eq { gsave 1 setgray fill grestore } if\n"); printf(" exch neg exch neg translate \n"); printf(" clip \n"); printf(" rotate \n"); printf(" 4 dict begin\n"); printf(" pathbbox /&top exch def\n"); printf(" /&right exch def\n"); printf(" /&bottom exch def\n"); printf(" &right sub /&width exch def\n"); printf(" newpath\n"); printf(" currentlinewidth mul round dup \n"); printf(" &bottom exch Jrnd exch &top \n"); printf(" 4 -1 roll currentlinewidth mul setlinewidth \n"); printf(" { &right exch moveto &width 0 rlineto stroke } for \n"); printf(" end\n"); printf(" grestore\n"); printf(" newpath\n"); printf("} bind def\n"); gsave(); setfont("Times-Roman", 9.00); if (gs->preamble != CNULL) { if (gs->prefile) { f = fopen(gs->preamble, "r"); if (f == NULL) { fprintf(stderr, "Error: preamble file %s couldn't be opened\n", gs->preamble); exit(1); } for (c = getc(f); c != real_eof; c = getc(f)) putchar(c); putchar('\n'); fclose(f); } else { printf("%s\n", gs->preamble); } } } draw_footer(gs, pp) Graphs gs; int pp; { FILE *f; char c; if (gs->epilogue != CNULL) { if (gs->epifile) { f = fopen(gs->epilogue, "r"); if (f == NULL) { fprintf(stderr, "Error: epilogue file %s couldn't be opened\n", gs->epilogue); exit(1); } for (c = getc(f); c != real_eof; c = getc(f)) putchar(c); putchar('\n'); fclose(f); } else { printf("%s\n", gs->epilogue); } } grestore(); if (pp) printf("showpage\n"); else printf("\n"); if (pp) { printf("%%%%PageTrailer\n"); } }