|
|
1.1 root 1: /*
2: * emit pic.
3: */
4:
5: #include "draw_dag.h"
6: #include "dag.h"
7: #include "parsedag.h"
8: #include "paths.h"
9:
10: static char* escape(char *s) {
11: static char buf[BUFSIZ];
12: char *p = buf;
13: while (*s) {
14: if (*s == '\"') *p++ = '\\';
15: *p++ = *s++;
16: }
17: *p = '\0';
18: return buf;
19: }
20:
21: char *expandesc(char*d, int node) {
22: static char buf[BUFSIZ];
23: char * p = buf;
24: char *printname;
25: if (Node[node]->label.type == STRING)
26: printname = Node[node]->label.value;
27: else
28: printname = Node[node]->name;
29:
30: while (*p = *d) switch(*p) {
31: case '\\':
32: if (!(*p++ = *++d)) return buf;
33: d++;
34: break;
35: case '$':
36: d++;
37: int m = 0;
38: if (!strncmp(d,"NAMELEN",m=7)) sprintf(p,"%d",strlen(printname));
39: else if (!strncmp(d,"NAME",m=4)) {
40: if (Node[node]->pointsize != Default_node.pointsize)
41: sprintf(p,"\\s%d\"%s\"\\s0",Node[node]->pointsize,
42: escape(printname));
43: else sprintf(p,"\"%s\"",escape(printname));
44: }
45: else if (!strncmp(d,"WIDTH",m=5)) sprintf(p,"%f",inchof(Node[node]->xsize));
46: else if (!strncmp(d,"HEIGHT",m=6)) sprintf(p,"%f",inchof(Node[node]->ysize));
47: else {p++; break;}
48: while (*p) p++;
49: d += m;
50: break;
51: default:
52: p++; d++; break;
53: }
54: return buf;
55: }
56:
57: char *pic_inkstr(dag_ink_t ink) {
58: switch(ink) {
59: case solid_ink: return ""; // Sys V pic doesn't like "solid".
60: case dashed_ink: return "dashed";
61: case dotted_ink: return "dotted";
62: case invis_ink: return "invis";
63: }
64: }
65:
66: char* find_cip_shape(shape_id_t s) {
67: switch (s) {
68: case Box:
69: case Square:
70: return "box wid %f ht %f";
71: case Diamond:
72: return "d = %f\ne=%f\nmove down e/2; line up e/2 right d/2 then up e/2 left d/2 then down e/2 left d/2 then down e/2 right d/2";
73: case Circle:
74: return "circle rad %f/2";
75: case Doublecircle:
76: return "circe rad %f/2; circle rad .9*%f/2 at last circle.c";
77: case User_defined:
78: case Ellipse:
79: default:
80: return "ellipse wid %f ht %f";
81: case Plaintext:
82: return "box invis wid %f ht %f";
83: }
84: }
85:
86: void emit_pic_pt(Point p) {
87: printf("(%f,%f)",inchof(p.x),inchof(p.y));
88: }
89:
90: void emit_pic_header() {
91:
92: static int ordinal = 0;
93: double sf = 1.;
94: if (User.width <= 0) printf(".PS\n"); // no args
95: else {
96: sf = min((User.width*Resolution)/Xmax,1.);
97: if (User.height <= 0) User.height = (double)Ymax/Resolution;
98: else sf = min((User.height*Resolution)/Ymax,sf);
99: if (sf == 1.) printf(".PS\n");
100: else {
101: User.width = min(User.width,sf*(double)Xmax/Resolution);
102: User.height = min(User.height,sf*(double)Ymax/Resolution);
103: Default_node.pointsize = (int)(Default_node.pointsize * sf);
104: for (int i = 0; i < N; i++)
105: Node[i]->pointsize = (int)(Node[i]->pointsize * sf);
106: printf(".PS %f %f\n",User.width,User.height);
107: }
108: }
109:
110: printf(".lf %d\n",Current_file.line_number + 1);
111: printf("arrowht = %f;\n", inchof((int)(Default_node.xsize*.15)));
112: printf("arrowwid = %f;\n", inchof((int)(Default_node.xsize*.075)));
113: if (!ordinal++ && (Output_type != Cip))
114: cat_libfile(DAGLIB_PIC);
115: unsquirrel();
116: }
117:
118: void emit_pic_node_header() {
119: printf(".ps %d\n",Default_node.pointsize);
120: }
121:
122: void emit_pic_edge_header() {
123: if (Default_edge.pointsize != Default_node.pointsize)
124: printf(".ps\n.ps %d\n",Default_edge.pointsize);
125: }
126:
127: void emit_pic_node(int node) {
128: shape_t shape = Node[node]->shape;
129: char *printname;
130: if (Node[node]->label.type == DESC) printname = "";
131: else if (Node[node]->label.type == STRING) printname = Node[node]->label.value;
132: else printname = Node[node]->name;
133:
134: if (shape.type == DESC) {
135: printf("Node%d: [ %s ] with .c at ",node,expandesc(Node[node]->shape.value,node));
136: emit_pic_pt(Node[node]->pos);
137: printf(";\n");
138: }
139: else {
140: if (Output_type == Cip) {
141: printf("[ ");
142: printf(find_cip_shape(Node[node]->shape.shape_id),
143: inchof(Node[node]->xsize),inchof(Node[node]->ysize));
144: printf("] with .c at ");
145: emit_pic_pt(Node[node]->pos);
146: printf(";\nmove to ");
147: emit_pic_pt(Node[node]->pos);
148: printf("; \"%s\";\n",escape(printname));
149: }
150: else {
151: printf("Node%d: %s(\"%s\",%f,%f) at ",node,Node[node]->shape.value,
152: escape(printname),inchof(Node[node]->xsize),inchof(Node[node]->ysize));
153: emit_pic_pt(Node[node]->pos);
154: printf(";\n");
155: }
156: }
157: if (Node[node]->label.type == DESC) {
158: printf("move to ");
159: emit_pic_pt(Node[node]->pos);
160: printf("%s;\n",Node[node]->label.value);
161: }
162: }
163:
164: void emit_pic_edgelabel(DAG_edge_t *e) {
165: if (!e->label.type) return;
166: printf("move to ");
167: emit_pic_pt(find_edge_midpoint(e));
168: printf("; ");
169: if (e->label.type == DESC) printf("%s;\n",e->label.value);
170: else printf("\"%s\";\n",escape(e->label.value));
171: }
172:
173: void emit_pic_edge(int node, DAG_edge_t *e) {
174: if (e->ink == invis_ink) return;
175: Point intersection;
176: int fromnode = node, tonode = e->node;
177: intersection = find_nodeport(fromnode,e->top,e->splinept[0]);
178: printf("spline %s %s from ",e->flipped?"<-":"->",
179: (Output_type != Cip? pic_inkstr(e->ink) : "") );
180: emit_pic_pt(intersection);
181:
182: for (int i = 1; e->splinept[i+1].x >= 0; i++) {
183: printf(" to ");
184: emit_pic_pt(e->splinept[i]);
185: }
186: intersection = find_nodeport(tonode,e->bottom,e->splinept[i]);
187: printf(" to ");
188: emit_pic_pt(intersection);
189: printf(";\n");
190: emit_pic_edgelabel(e);
191: }
192:
193: void emit_pic_trailer() {
194: printf(".ps\n.PE\n");
195: printf(".lf %d\n",Current_file.line_number + 1);
196: }
197:
198: void emit_pic() {
199: int node;
200: DAG_edge_t *e;
201:
202: emit_pic_header();
203: emit_pic_node_header();
204: for (node = 0; node < N; node++) emit_pic_node(node);
205: emit_pic_edge_header();
206: for (node = 0; node < N; node++)
207: for (e = Edge[node]; e; e = e->nextof())
208: emit_pic_edge(node,e);
209: emit_pic_trailer();
210: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.