1 /* hgraph.c 1.3 (Berkeley) 83/08/03 2 * 3 * This file contains the graphics routines for converting gremlin 4 * pictures to troff input. 5 */ 6 7 #include "gprint.h" 8 9 10 #define MAXVECT 50 11 #define pi 3.14159265358979324 12 #define twopi (2.0 * pi) 13 #define len(a, b) sqrt((b.x-a.x) * (b.x-a.x) + (b.y-a.y) * (b.y-a.y)) 14 15 16 extern int style[]; /* line and character styles */ 17 extern int thick[]; 18 extern char *tfont[]; 19 extern char *tsize[]; 20 21 22 extern double scale; /* imports from main.c */ 23 extern double troffscale; 24 extern point(); 25 extern int linethickness; 26 extern int linmod; 27 extern int lastx; 28 extern int lasty; 29 extern int lastyline; 30 extern int ytop; 31 extern int ybottom; 32 extern int xleft; 33 extern int xright; 34 35 36 /*----------------------------------------------------------------------------* 37 | Routine: HGPrintElt (element_pointer) 38 | 39 | Results: examines a picture element and calls the appropriate 40 | routine(s) to print them according to their type. 41 | After the picture is drawn, current position is (lastx, lasty). 42 *----------------------------------------------------------------------------*/ 43 44 HGPrintElt(element) 45 ELT *element; 46 { 47 register POINT *p1; 48 register POINT *p2; 49 register int length; 50 51 if ( !DBNullelt(element) ) { 52 p1 = element->ptlist; /* p1 always has first point */ 53 if (TEXT(element->type)) { 54 HGSetFont(element->brushf, element->size); 55 HGPutText(element->type, *p1, element->textpt); 56 } else { 57 HGSetBrush(element->brushf); /* graphics need brush set */ 58 switch (element->type) { 59 60 case ARC: p2 = PTNextPoint(p1); 61 doarc(*p1, *p2, element->size); 62 break; 63 64 case CURVE: tmove(p1); 65 printf("\\D'g"); 66 while (!Nullpoint((p1 = PTNextPoint(p1)))) { 67 dx((double) p1->x); 68 dy((double) p1->y); 69 } /* end while */; 70 putchar('\''); 71 break; 72 73 case VECTOR: length = 1; /* keep track of line length */ 74 tmove(p1); /* so single lines don't get long */ 75 while (!Nullpoint((p1 = PTNextPoint(p1)))) { 76 printf("\\D'l"); 77 dx((double) p1->x); 78 dy((double) p1->y); 79 putchar('\''); 80 if (length++ > MAXVECT) { 81 tmove (p1); 82 length = 1; 83 } 84 } /* end while */ 85 break; 86 } /* end switch */ 87 } /* end else Text */ 88 } /* end if */ 89 } /* end PrintElt */ 90 91 92 /*----------------------------------------------------------------------------* 93 | Routine: HGPutText (justification, position_point, string) 94 | 95 | Results: given the justification, a point to position with, and a 96 | string to put, HGPutText first sends the string into a 97 | diversion, moves to the positioning point, then outputs local 98 | vertical and horizontal motions as needed to justify the text. 99 | After all motions are done, the diversion is printed out. 100 *----------------------------------------------------------------------------*/ 101 102 HGPutText(justify,pnt,string) 103 int justify; 104 POINT pnt; 105 char string[]; 106 { 107 printf(".di gt\n\\&%s\n.di", string); /* divert the text. */ 108 tmove(&pnt); /* move to positioning point */ 109 switch (justify) { 110 /* local vertical motions */ 111 case CENTLEFT: 112 case CENTCENT: 113 case CENTRIGHT: printf("\\v'(\\n(dnu+1m)/2u'"); /* down half */ 114 break; 115 116 case TOPLEFT: 117 case TOPCENT: 118 case TOPRIGHT: printf("\\v'\\n(dnu+1m'"); /* down whole */ 119 } 120 121 switch (justify) { 122 /* local horizontal motions */ 123 case BOTCENT: 124 case CENTCENT: 125 case TOPCENT: printf("\\h'-\\n(dlu/2u'"); /* back half */ 126 break; 127 128 case BOTRIGHT: 129 case CENTRIGHT: 130 case TOPRIGHT: printf("\\h'-\\n(dlu'"); /* back whole */ 131 } 132 /* now print the text. The (cr) at the end */ 133 printf("\\c\n.gt\n"); /* results in a blank line in the output. It */ 134 /* is necessary to break the "\c" directive. */ 135 } /* end HGPutText */ 136 137 138 /*----------------------------------------------------------------------------* 139 | Routine: doarc (center_point, start_point, angle) 140 | 141 | Results: produces either drawarc command or a drawcircle command 142 | depending on the angle needed to draw through. 143 *----------------------------------------------------------------------------*/ 144 145 doarc (cp, sp, angle) 146 POINT cp; 147 POINT sp; 148 int angle; 149 { 150 double radius = len(cp, sp); 151 double radians; 152 153 154 if (angle) { /* arc with angle */ 155 tmove (&sp); /* starting point first */ 156 printf("\\D'a"); 157 dx((double) cp.x); /* move to center */ 158 dy((double) cp.y); 159 160 radians = acos((sp.x - cp.x) / radius); /* angle of ending */ 161 if (cp.y - sp.y < 0.0) /* point calculated */ 162 radians = twopi - radians; /* from start point */ 163 radians += ((double) angle) * (pi / 180.0); /* and arc's angle */ 164 if (radians > twopi) radians -= twopi; 165 166 dx(cp.x + cos(radians) * radius); /* move to ending point */ 167 dy(cp.y - sin(radians) * radius); 168 169 } else { /* a full circle (angle == 0) */ 170 cp.x -= radius; 171 tmove(&cp); /* move to the left point first */ 172 /* draw circle with given diameter */ 173 printf("\\D'c %du", (int) ((radius + radius) * troffscale)); 174 } 175 putchar('\''); /* finish the command */ 176 } 177 178 179 /*----------------------------------------------------------------------------* 180 | Routine: HGSetFont (font_number, Point_size) 181 | 182 | Results: ALWAYS outputs a .ft and .ps directive to troff. This is 183 | done because someone may change stuff inside a text string. 184 *----------------------------------------------------------------------------*/ 185 186 HGSetFont(font, size) 187 int font, size; 188 { 189 cr(); 190 printf(".ft %s\n.ps %s\n", tfont[font-1], tsize[size-1]); 191 } 192 193 194 /*----------------------------------------------------------------------------* 195 | Routine: HGSetBrush (line_mode) 196 | 197 | Results: generates the troff commands to set up the line width and 198 | style of subsequent lines. Does nothing if no change is needed. 199 | 200 | Side Efct: sets "linmode" and "linethicknes" 201 *----------------------------------------------------------------------------*/ 202 203 HGSetBrush(mode) 204 int mode; 205 { 206 if (linmod != style[--mode]) { 207 cr(); 208 printf ("\\D's %du'",linmod = style[mode]); 209 } 210 if (linethickness != thick[mode]) { 211 cr(); 212 printf ("\\D't %du'", linethickness = thick[mode]); 213 } 214 } 215 216 217 /*----------------------------------------------------------------------------* 218 | Routine: dx (x_destination) 219 | 220 | Results: scales and outputs a number for delta x (with a leading space) 221 | given "lastx" and x_destination. 222 | 223 | Side Efct: resets "lastx" to x_destination. 224 *----------------------------------------------------------------------------*/ 225 226 dx(x) 227 double x; 228 { 229 register int ix = (int) (x * troffscale); 230 231 printf(" %du", ix - lastx); 232 lastx = ix; 233 } 234 235 236 /*----------------------------------------------------------------------------* 237 | Routine: dy (y_destination) 238 | 239 | Results: scales and outputs a number for delta y (with a leading space) 240 | given "lastyline" and y_destination. 241 | 242 | Side Efct: resets "lastyline" to y_destination. Since "line" vertical 243 | motions don't affect "page" ones, "lasty" isn't updated. 244 *----------------------------------------------------------------------------*/ 245 246 dy(y) 247 double y; 248 { 249 register int iy = (int) (y * troffscale); 250 251 printf(" %du", iy - lastyline); 252 lastyline = iy; 253 } 254 255 256 /*----------------------------------------------------------------------------* 257 | Routine: tmove (point_pointer) 258 | 259 | Results: produces horizontal and vertical moves for troff given the 260 | pointer of a point to move to. 261 *----------------------------------------------------------------------------*/ 262 263 tmove(ptr) 264 POINT *ptr; 265 { 266 register int ix = (int) (ptr->x * troffscale); 267 register int iy = (int) (ptr->y * troffscale); 268 register int dx; 269 register int dy; 270 271 cr(); 272 if (dy = iy - lasty) { 273 printf(".sp %du\n", dy); 274 } 275 lastyline = lasty = iy; 276 if (dx = ix - lastx) { 277 printf("\\h'%du'", dx); 278 lastx = ix; 279 } 280 } 281 282 283 /*----------------------------------------------------------------------------* 284 | Routine: cr ( ) 285 | 286 | Results: breaks the output line up to not overrun troff with lines that 287 | are too long. 288 | 289 | Side Efct: sets "lastx" to "xleft" for troff's return to left margin 290 *----------------------------------------------------------------------------*/ 291 292 cr() 293 { 294 putchar('\n'); 295 lastx = xleft; 296 } 297