Annotation of researchv10no/cmd/dag/emit_ps.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.