Annotation of researchv10no/cmd/dag/emit_ps.c, revision 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.