URI:
       tlinegen.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tlinegen.c (4704B)
       ---
            1 #include        <math.h>
            2 #include        <stdio.h>
            3 #include        "pic.h"
            4 #include        "y.tab.h"
            5 
            6 obj*
            7 linegen(int type)
            8 {
            9         static double prevdx = HT;
           10         static double prevdy = 0;
           11         static double prevw = HT10;
           12         static double prevh = HT5;
           13         int i, j, some, head, ddtype, invis, chop;
           14         double ddval, chop1, chop2, x0, y0, x1, y1;
           15         double theta;
           16         double defx, defy;
           17         obj *p, *ppos;
           18         static int xtab[] = { 1, 0, -1, 0 };        /* R=0, U=1, L=2, D=3 */
           19         static int ytab[] = { 0, 1, 0, -1 };
           20         double dx[500], dy[500];
           21         int ndxy;
           22         double nx, ny;
           23         Attr *ap;
           24 
           25         nx = curx;
           26         ny = cury;
           27         defx = getfval("linewid");
           28         defy = getfval("lineht");
           29         prevh = getfval("arrowht");
           30         prevw = getfval("arrowwid");
           31         dx[0] = dy[0] = ndxy = some = head = invis = 0;
           32         chop = chop1 = chop2 = 0;
           33         ddtype = ddval = 0;
           34         for (i = 0; i < nattr; i++) {
           35                 ap = &attr[i];
           36                 switch (ap->a_type) {
           37                 case TEXTATTR:
           38                         savetext(ap->a_sub, ap->a_val.p);
           39                         break;
           40                 case HEAD:
           41                         head += ap->a_val.i;
           42                         break;
           43                 case INVIS:
           44                         invis = INVIS;
           45                         break;
           46                 case CHOP:
           47                         if (chop++ == 0)
           48                                 chop1 = chop2 = ap->a_val.f;
           49                         else
           50                                 chop2 = ap->a_val.f;
           51                         break;
           52                 case DOT:
           53                 case DASH:
           54                         ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
           55                         if (ap->a_sub == DEFAULT)
           56                                 ddval = getfval("dashwid");
           57                         else
           58                                 ddval = ap->a_val.f;
           59                         break;
           60                 case SAME:
           61                         dx[ndxy] = prevdx;
           62                         dy[ndxy] = prevdy;
           63                         some++;
           64                         break;
           65                 case LEFT:
           66                         dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
           67                         some++;
           68                         hvmode = L_DIR;
           69                         break;
           70                 case RIGHT:
           71                         dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
           72                         some++;
           73                         hvmode = R_DIR;
           74                         break;
           75                 case UP:
           76                         dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
           77                         some++;
           78                         hvmode = U_DIR;
           79                         break;
           80                 case DOWN:
           81                         dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
           82                         some++;
           83                         hvmode = D_DIR;
           84                         break;
           85                 case HEIGHT:        /* length of arrowhead */
           86                         prevh = ap->a_val.f;
           87                         break;
           88                 case WIDTH:        /* width of arrowhead */
           89                         prevw = ap->a_val.f;
           90                         break;
           91                 case TO:
           92                         if (some) {
           93                                 nx += dx[ndxy];
           94                                 ny += dy[ndxy];
           95                                 ndxy++;
           96                                 dx[ndxy] = dy[ndxy] = some = 0;
           97                         }
           98                         ppos = attr[i].a_val.o;
           99                         dx[ndxy] = ppos->o_x - nx;
          100                         dy[ndxy] = ppos->o_y - ny;
          101                         some++;
          102                         break;
          103                 case BY:
          104                         if (some) {
          105                                 nx += dx[ndxy];
          106                                 ny += dy[ndxy];
          107                                 ndxy++;
          108                                 dx[ndxy] = dy[ndxy] = some = 0;
          109                         }
          110                         ppos = ap->a_val.o;
          111                         dx[ndxy] = ppos->o_x;
          112                         dy[ndxy] = ppos->o_y;
          113                         some++;
          114                         break;
          115                 case THEN:        /* turn off any previous accumulation */
          116                         if (some) {
          117                                 nx += dx[ndxy];
          118                                 ny += dy[ndxy];
          119                                 ndxy++;
          120                                 dx[ndxy] = dy[ndxy] = some = 0;
          121                         }
          122                         break;
          123                 case FROM:
          124                 case AT:
          125                         ppos = ap->a_val.o;
          126                         nx = curx = ppos->o_x;
          127                         ny = cury = ppos->o_y;
          128                         break;
          129                 }
          130         }
          131         if (some) {
          132                 nx += dx[ndxy];
          133                 ny += dy[ndxy];
          134                 ndxy++;
          135                 defx = dx[ndxy-1];
          136                 defy = dy[ndxy-1];
          137         } else {
          138                 defx *= xtab[hvmode];
          139                 defy *= ytab[hvmode];
          140                 dx[ndxy] = defx;
          141                 dy[ndxy] = defy;
          142                 ndxy++;
          143                 nx += defx;
          144                 ny += defy;
          145         }
          146         prevdx = defx;
          147         prevdy = defy;
          148         if (chop) {
          149                 if (chop == 1 && chop1 == 0)        /* just said "chop", so use default */
          150                         chop1 = chop2 = getfval("circlerad");
          151                 theta = atan2(dy[0], dx[0]);
          152                 x0 = chop1 * cos(theta);
          153                 y0 = chop1 * sin(theta);
          154                 curx += x0;
          155                 cury += y0;
          156                 dx[0] -= x0;
          157                 dy[0] -= y0;
          158 
          159                 theta = atan2(dy[ndxy-1], dx[ndxy-1]);
          160                 x1 = chop2 * cos(theta);
          161                 y1 = chop2 * sin(theta);
          162                 nx -= x1;
          163                 ny -= y1;
          164                 dx[ndxy-1] -= x1;
          165                 dy[ndxy-1] -= y1;
          166                 dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
          167                         x0, y0, x1, y1, curx, cury, nx, ny);
          168         }
          169         p = makenode(type, 5 + 2 * ndxy);
          170         curx = p->o_val[0] = nx;
          171         cury = p->o_val[1] = ny;
          172         if (head || type == ARROW) {
          173                 p->o_nhead = getfval("arrowhead");
          174                 p->o_val[2] = prevw;
          175                 p->o_val[3] = prevh;
          176                 if (head == 0)
          177                         head = HEAD2;        /* default arrow head */
          178         }
          179         p->o_attr = head | invis | ddtype;
          180         p->o_val[4] = ndxy;
          181         nx = p->o_x;
          182         ny = p->o_y;
          183         for (i = 0, j = 5; i < ndxy; i++, j += 2) {
          184                 p->o_val[j] = dx[i];
          185                 p->o_val[j+1] = dy[i];
          186                 if (type == LINE || type == ARROW)
          187                         extreme(nx += dx[i], ny += dy[i]);
          188                 else if (type == SPLINE && i < ndxy-1) {
          189                         /* to compute approx extreme of spline at p,
          190                         /* compute midway between p-1 and p+1,
          191                         /* then go 3/4 from there to p */
          192                         double ex, ey, xi, yi, xi1, yi1;
          193                         xi = nx + dx[i]; yi = ny + dy[i];        /* p */
          194                         xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1];        /* p+1 */
          195                         ex = (nx+xi1)/2; ey = (ny+yi1)/2;        /* midway */
          196                         ex += 0.75*(xi-ex); ey += 0.75*(yi-ey);
          197                         extreme(ex, ey);
          198                         nx = xi; ny = yi;
          199                 }
          200 
          201         }
          202         p->o_ddval = ddval;
          203         if (dbg) {
          204                 printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
          205                 for (i = 0, j = 5; i < ndxy; i++, j += 2)
          206                         printf("%g %g\n", p->o_val[j], p->o_val[j+1]);
          207         }
          208         extreme(p->o_x, p->o_y);
          209         extreme(curx, cury);
          210         return(p);
          211 }