|
|
1.1 ! root 1: /* ! 2: * emit PostScript. ! 3: * ! 4: */ ! 5: ! 6: #include "draw_dag.h" ! 7: #include "dag.h" ! 8: #include "parsedag.h" ! 9: #include "paths.h" ! 10: ! 11: static double PS_scalefactor; ! 12: static dag_ink_t Current_PS_ink; ! 13: ! 14: static Point Page_min,Page_max; ! 15: static Point PS_page_size,PS_Margin; ! 16: static int Pages_across, Pages_up; ! 17: static int Page_number = 0; ! 18: ! 19: static char* escape(char *s) { ! 20: static char buf[BUFSIZ]; ! 21: char *p = buf; ! 22: while (*s) { ! 23: if ((*s == '(') || (*s == ')')) *p++ = '\\'; ! 24: *p++ = *s++; ! 25: } ! 26: *p = '\0'; ! 27: return buf; ! 28: } ! 29: ! 30: void emit_ps_setink(dag_ink_t ink) { ! 31: char *inkstr; ! 32: switch(ink) { ! 33: case solid_ink: ! 34: inkstr = "[] 0"; break; ! 35: case dashed_ink: ! 36: inkstr = "[9 9 idtransform abs ceiling exch abs ceiling exch] 0"; break; ! 37: case dotted_ink: ! 38: inkstr = "[1 6 idtransform abs ceiling exch abs ceiling exch] 0"; break; ! 39: case invis_ink: ! 40: inkstr = "[0 1] 1"; break; ! 41: } ! 42: printf("%s setdash\n",inkstr); ! 43: Current_PS_ink = ink; ! 44: } ! 45: ! 46: void emit_ps_header() { ! 47: if (!Page_number) { ! 48: printf("%%! PostScript\n%%%%EndComments\n"); ! 49: printf("/Reset_Node_Pointsize %d def\n",Reset_node.pointsize); ! 50: printf("/Reset_Edge_Pointsize %d def\n",Reset_edge.pointsize); ! 51: printf("/coordfont /Times-Roman findfont 6 scalefont def\n"); ! 52: cat_libfile(DAGLIB_PS); ! 53: } ! 54: ! 55: PS_scalefactor = 1.; ! 56: if (User.width > 0) { ! 57: PS_scalefactor = min((User.width*Resolution)/Xmax,1.); ! 58: if (User.height <= 0) User.height = (double)Ymax/Resolution; ! 59: else PS_scalefactor = min((User.height*Resolution)/Ymax,PS_scalefactor); ! 60: } ! 61: if ((Page_size.x == 0) && (Page_size.y == 0) && (User.width != 0)) { ! 62: PS_page_size.x = round(User.width * Resolution / PS_scalefactor); ! 63: PS_page_size.y = round(User.height * Resolution / PS_scalefactor); ! 64: } ! 65: else { ! 66: if (Page_size.x) { ! 67: PS_page_size.x = round(Page_size.x / PS_scalefactor); ! 68: PS_page_size.y = round(Page_size.y / PS_scalefactor); ! 69: } ! 70: else { ! 71: PS_page_size.x = Xmax; ! 72: PS_page_size.y = Ymax; ! 73: } ! 74: } ! 75: PS_Margin.x = (int)(Margin.x/PS_scalefactor); ! 76: PS_Margin.y = (int)(Margin.x/PS_scalefactor); ! 77: printf("save\n"); ! 78: ! 79: if (Default_node.pointsize != Reset_node.pointsize) ! 80: printf("/dagnodefont dagnodefont %.3f scalefont def\n", ! 81: Default_node.pointsize/(double)Reset_node.pointsize); ! 82: if (Default_edge.pointsize != Reset_edge.pointsize) ! 83: printf("/dagedgefont dagedgefont %.3f scalefont def\n", ! 84: Default_edge.pointsize/(double)Reset_edge.pointsize); ! 85: printf("/coordfont /Times-Roman findfont %d scalefont def\n",(int)(6/PS_scalefactor)); ! 86: if (PS_scalefactor != 1.) printf("%.3f %.3f scale\n",PS_scalefactor,PS_scalefactor); ! 87: printf("/arrowlength %d def\n",Default_node.ysize/5); ! 88: printf("/arrowwidth arrowlength 2 div def\n"); ! 89: unsquirrel(); // inside save region, so will not affect global defs ! 90: printf("%%%%EndProlog\n"); ! 91: } ! 92: ! 93: void emit_ps_node_header() { ! 94: printf("dagnodefont setfont\n"); ! 95: } ! 96: ! 97: void emit_ps_edge_header() { ! 98: emit_ps_setink(Default_edge.ink); ! 99: Current_PS_ink = Default_edge.ink; ! 100: printf("dagedgefont setfont\n"); ! 101: } ! 102: ! 103: /* emit drawing code for an edge label */ ! 104: void emit_ps_edgelabel(DAG_edge_t *e) { ! 105: if (!e->label.type) return; // no label ! 106: if (e->pointsize != Default_edge.pointsize) ! 107: printf("dagedgefont %.3f scalefont setfont\n", ! 108: PS_scalefactor * e->pointsize / Default_edge.pointsize); ! 109: Point midpoint = find_edge_midpoint(e); ! 110: printf("%d %d moveto\n",midpoint.x,midpoint.y); ! 111: switch (e->label.type) { ! 112: case DESC: ! 113: printf("gsave\n%s\ngrestore\n",e->label.value); ! 114: break; ! 115: case STRING: ! 116: printf("(%s) show\n",escape(e->label.value)); ! 117: } ! 118: if (e->pointsize != Default_edge.pointsize) ! 119: printf("dagedgefront setfont\n"); ! 120: } ! 121: ! 122: void emit_ps_node(int node) { ! 123: char *printname; ! 124: if (Node[node]->label.type == STRING) ! 125: printname = Node[node]->label.value; ! 126: else if (Node[node]->label.type == DESC) ! 127: printname = ""; ! 128: else printname = Node[node]->name; ! 129: printf("%d %d moveto\n",Node[node]->pos.x,Node[node]->pos.y); ! 130: if (Node[node]->color) ! 131: printf("gsave %s setdagcolor\n",Node[node]->color); ! 132: if (Node[node]->pointsize != Default_node.pointsize) ! 133: printf("dagnodefont %.3f scalefont setfont\n", ! 134: (PS_scalefactor*Node[node]->pointsize)/Default_node.pointsize); ! 135: if (Node[node]->shape.type == STRING) ! 136: printf("(%s) %d %d %s\n",escape(printname),Node[node]->xsize,Node[node]->ysize,Node[node]->shape.value); ! 137: else printf("%s\n",Node[node]->shape.value); ! 138: if (Node[node]->label.type == DESC) { ! 139: printf("%d %d moveto\n",Node[node]->pos.x,Node[node]->pos.y); ! 140: printf("%s\n",Node[node]->label.value); ! 141: } ! 142: if (Node[node]->pointsize != Default_node.pointsize) ! 143: printf("dagnodefont setfont\n"); ! 144: if (Node[node]->color) ! 145: printf("grestore\n"); ! 146: } ! 147: ! 148: /* ! 149: * generate PS code to place node intersection on stack. ! 150: * intersection is the ray from rayorg through rayinter ! 151: */ ! 152: void emit_ps_nodeport(int node,Point rayorg, Point rayinter) { ! 153: printf(" %d %d %d %d %d %d ",Node[node]->xsize,Node[node]->ysize,rayorg.x - Node[node]->pos.x,rayorg.y - Node[node]->pos.y,rayinter.x - Node[node]->pos.x,rayinter.y - Node[node]->pos.y); ! 154: printf("%s_clip\n",Node[node]->shape.type == STRING? Node[node]->shape.value : Default_node.shape.value); ! 155: printf("%d add exch %d add exch\n",Node[node]->pos.y,Node[node]->pos.x); ! 156: } ! 157: ! 158: Point find_seg_midpoint(Point p0, Point p1) { ! 159: Point rv; ! 160: rv.x = (p0.x + p1.x) / 2; ! 161: rv.y = (p0.y + p1.y) / 2; ! 162: return rv; ! 163: } ! 164: ! 165: void emit_ps_edge(int node, DAG_edge_t *e) { ! 166: if (e->ink == invis_ink) return; ! 167: int fromnode = node, tonode = e->node; ! 168: if (e->ink != Current_PS_ink) emit_ps_setink(e->ink); ! 169: printf("%% %s %s edge\n",Node[fromnode]->name,Node[tonode]->name); ! 170: if (e->color != 0) {printf("gsave %s setdagcolor\n",e->color);} ! 171: ! 172: printf("newpath "); ! 173: emit_ps_nodeport(fromnode,e->top,e->splinept[0]); printf("moveto\n"); ! 174: Point mp = find_seg_midpoint(e->splinept[0],e->splinept[1]); ! 175: if (e->flipped) ! 176: printf("%d %d makearrow\n",e->top.x,e->top.y); ! 177: printf(" %d %d lineto\n",mp.x,mp.y); ! 178: ! 179: for (int i = 1; e->splinept[i + 1].x >= 0; i++) { ! 180: Point mp = find_seg_midpoint(e->splinept[i],e->splinept[i+1]); ! 181: printf("%d %d 2 copy %d %d curveto\n", ! 182: e->splinept[i].x,e->splinept[i].y,mp.x,mp.y); ! 183: } ! 184: emit_ps_nodeport(tonode,e->bottom,e->splinept[i]); ! 185: printf("lineto currentpoint stroke moveto\n"); ! 186: if (!e->flipped) ! 187: printf("%d %d makearrow\n",e->bottom.x,e->bottom.y); ! 188: printf("stroke\n"); ! 189: ! 190: if (e->color != 0) {printf("grestore\n");} ! 191: emit_ps_edgelabel(e); ! 192: } ! 193: ! 194: void emit_ps_trailer() { ! 195: printf("restore\n"); ! 196: } ! 197: ! 198: void emit_ps_page() { ! 199: printf("showpage\ngrestore\n"); ! 200: } ! 201: ! 202: int n_ps_pages() { ! 203: int rv; ! 204: Pages_across = Xmax / PS_page_size.x; ! 205: if (Pages_across != (double)Xmax/PS_page_size.x) Pages_across++; ! 206: Pages_up = Ymax / PS_page_size.y; ! 207: if (Pages_up != (double)Ymax/PS_page_size.y) Pages_up++; ! 208: rv = Pages_across * Pages_up; ! 209: return rv; ! 210: } ! 211: ! 212: void emit_ps_set_page(int page) { ! 213: int row = page % Pages_up; ! 214: int col = (page - row) / Pages_up; ! 215: Page_min.x = col * PS_page_size.x; ! 216: Page_min.y = row * PS_page_size.y; ! 217: Page_max.x = Page_min.x + PS_page_size.x; ! 218: Page_max.y = Page_min.y + PS_page_size.y; ! 219: printf("%%%%Page: %s %d\n",Current_file.name,++Page_number); ! 220: printf("%%%%BoundingBox: %d %d %d %d\n", ! 221: PS_Margin.x-1,PS_Margin.y-1,PS_Margin.x+PS_page_size.x+1,PS_Margin.y+PS_page_size.y+1); ! 222: printf("gsave\n"); ! 223: /* page coord before clip so it can be in the margin if ever change this */ ! 224: if ((Pages_up > 1) || (Pages_across > 1)) ! 225: printf("coordfont setfont %d %d moveto (%d,%d) show\n", ! 226: PS_Margin.x,PS_Margin.y,col,row); ! 227: printf("%d %d moveto %d 0 rlineto 0 %d rlineto %d 0 rlineto closepath clip newpath\n", ! 228: PS_Margin.x-1,PS_Margin.y-1,PS_page_size.x+2,PS_page_size.y+2,-PS_page_size.x-2); // off by one pixel? ! 229: printf("%d %d translate\n",PS_Margin.x - Page_min.x,PS_Margin.y - Page_min.y); ! 230: } ! 231: ! 232: int node_in_page(int node) { ! 233: int halfx = Node[node]->xsize / 2; ! 234: int halfy = Node[node]->ysize / 2; ! 235: for (int xcorner = Node[node]->pos.x - halfx; xcorner <= Node[node]->pos.x + halfx; xcorner += halfx) { ! 236: for (int ycorner = Node[node]->pos.y - halfy; ycorner <= Node[node]->pos.y + halfy; ycorner += halfy) { ! 237: if ((ycorner >= Page_min.y) && (ycorner <= Page_max.y) ! 238: && (xcorner >= Page_min.x) && (xcorner <= Page_max.x)) ! 239: return 1; ! 240: } ! 241: } ! 242: return 0; ! 243: } ! 244: ! 245: int edge_in_page(DAG_edge_t* e) { ! 246: for (int i = 0; e->splinept[i+1].x >= 0; i++) { ! 247: Point pt0 = e->splinept[i]; ! 248: Point pt1 = e->splinept[i+1]; ! 249: if (!(((pt0.x < Page_min.x) && (pt1.x < Page_min.x)) || ! 250: ((pt0.x > Page_max.x) && (pt1.x > Page_max.x)) || ! 251: ((pt0.y < Page_min.y) && (pt1.y < Page_min.y)) || ! 252: ((pt0.y > Page_max.y) && (pt1.y > Page_max.y)))) return 1; ! 253: } ! 254: return 0; ! 255: } ! 256: ! 257: void emit_ps() { ! 258: int node; ! 259: DAG_edge_t *e; ! 260: int maxpage; ! 261: ! 262: emit_ps_header(); ! 263: maxpage = n_ps_pages(); ! 264: for (int page = 0; page < maxpage; page++) { ! 265: emit_ps_set_page(page); ! 266: emit_ps_node_header(); ! 267: for (node = 0; node < N; node++) ! 268: if (node_in_page(node)) emit_ps_node(node); ! 269: emit_ps_edge_header(); ! 270: for (node = 0; node < N; node++) ! 271: for (e = Edge[node]; e; e = e->nextof()) ! 272: if (edge_in_page(e)) emit_ps_edge(node,e); ! 273: emit_ps_page(); ! 274: } ! 275: emit_ps_trailer(); ! 276: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.