1 /* hgraph.c 1.14 (Berkeley) 84/11/27 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 40 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 int tsize[]; 20 extern int stipple_index[]; /* stipple font index for stipples 1 - 8 */ 21 extern char *stipple; /* stipple type (cf or ug) */ 22 23 24 extern double troffscale; /* imports from main.c */ 25 extern point(); 26 extern int linethickness; 27 extern int linmod; 28 extern int lastx; 29 extern int lasty; 30 extern int lastyline; 31 extern int ytop; 32 extern int ybottom; 33 extern int xleft; 34 extern int xright; 35 36 37 /*----------------------------------------------------------------------------* 38 | Routine: HGPrintElt (element_pointer, baseline) 39 | 40 | Results: examines a picture element and calls the appropriate 41 | routine(s) to print them according to their type. 42 | After the picture is drawn, current position is (lastx, lasty). 43 *----------------------------------------------------------------------------*/ 44 45 HGPrintElt(element, baseline) 46 ELT *element; 47 int baseline; 48 { 49 register POINT *p1; 50 register POINT *p2; 51 register int length; 52 static int didstipple = 1; /* flag to prevent multipe messages about no */ 53 /* stipple font requested from being printed */ 54 float firstx, firsty; /* for completing polygons */ 55 56 if ( !DBNullelt(element) && !Nullpoint((p1 = element->ptlist))) { 57 /* p1 always has first point */ 58 if (TEXT(element->type)) { 59 HGSetFont(element->brushf, element->size); 60 HGPutText(element->type, *p1, element->textpt); 61 } else { 62 if (element->brushf) { /* if there is a brush, the */ 63 HGSetBrush(element->brushf); /* graphics need it set */ 64 } 65 switch (element->type) { 66 67 case ARC: p2 = PTNextPoint(p1); 68 doarc(*p1, *p2, element->size); 69 break; 70 71 case CURVE: tmove(p1); 72 printf("\\D'g"); 73 while (!Nullpoint((p1 = PTNextPoint(p1)))) { 74 dx((double) p1->x); 75 dy((double) p1->y); 76 } /* end while */; 77 putchar('\''); 78 cr(); 79 break; 80 81 case VECTOR: length = 1; /* keep track of line length */ 82 tmove(p1); /* so single lines don't get long */ 83 while (!Nullpoint((p1 = PTNextPoint(p1)))) { 84 printf("\\D'l"); 85 dx((double) p1->x); 86 dy((double) p1->y); 87 putchar('\''); 88 if (length++ > MAXVECT) { 89 cr(); 90 tmove (p1); 91 length = 1; 92 } 93 } /* end while */ 94 cr(); 95 break; 96 97 case POLYGON: tmove(p1); 98 if (stipple) { 99 didstipple = 1; 100 if (element->brushf) { 101 printf("\\D'p %d", 102 element->size <= NSTIPPLES ? 103 stipple_index[element->size - 1] : 104 element->size); 105 } else { 106 printf("\\D'P %d", 107 element->size <= NSTIPPLES ? 108 stipple_index[element->size - 1] : 109 element->size); 110 } 111 } else { 112 if (didstipple) { 113 error("no stipple font requested for picture at line %d", baseline); 114 didstipple = 0; 115 } 116 printf("\\D'p 0"); 117 } 118 119 firstx = p1->x; 120 firsty = p1->y; 121 while (!Nullpoint((PTNextPoint(p1)))) { 122 p1 = PTNextPoint(p1); 123 dx((double) p1->x); 124 dy((double) p1->y); 125 } /* end while */; 126 127 /* close polygon if not done so by user */ 128 if ((firstx != p1->x) || (firsty != p1->y)) { 129 dx((double) firstx); 130 dy((double) firsty); 131 } 132 133 putchar('\''); 134 cr(); 135 break; 136 } /* end switch */ 137 } /* end else Text */ 138 } /* end if */ 139 } /* end PrintElt */ 140 141 142 /*----------------------------------------------------------------------------* 143 | Routine: HGPutText (justification, position_point, string) 144 | 145 | Results: given the justification, a point to position with, and a 146 | string to put, HGPutText first sends the string into a 147 | diversion, moves to the positioning point, then outputs local 148 | vertical and horizontal motions as needed to justify the text. 149 | After all motions are done, the diversion is printed out. 150 *----------------------------------------------------------------------------*/ 151 152 HGPutText(justify,pnt,string) 153 int justify; 154 POINT pnt; 155 register char *string; 156 { 157 int savelasty = lasty; /* vertical motion for text is to be */ 158 /* ignored. save current y here */ 159 160 printf(".nr g8 \\n(.d\n"); /* save current vertical position. */ 161 printf(".ds g9 \""); /* define string containing the text. */ 162 while (*string) { /* put out the string */ 163 if (*string == '\\' && *(string+1) == '\\') { /* one character at a */ 164 printf("\\\\\\"); /* time replacing // */ 165 string++; /* by //// to prevent */ 166 } /* interpretation at */ 167 printf("%c", *(string++)); /* printout time */ 168 } 169 printf("\n"); 170 tmove(&pnt); /* move to positioning point */ 171 switch (justify) { 172 /* local vertical motions */ 173 /* (the numbers here are used to be */ 174 /* somewhat compatible with gprint) */ 175 case CENTLEFT: 176 case CENTCENT: 177 case CENTRIGHT: printf("\\v'0.85n'"); /* down half */ 178 break; 179 180 case TOPLEFT: 181 case TOPCENT: 182 case TOPRIGHT: printf("\\v'1.7n'"); /* down whole */ 183 } 184 185 switch (justify) { 186 /* local horizontal motions */ 187 case BOTCENT: 188 case CENTCENT: 189 case TOPCENT: printf("\\h-\\w\\*(g9u/2u"); /* back half */ 190 break; 191 192 case BOTRIGHT: 193 case CENTRIGHT: 194 case TOPRIGHT: printf("\\h-\\w\\*(g9u"); /* back whole */ 195 } 196 197 printf("\\&\\*(g9\n"); /* now print the text. */ 198 printf(".sp |\\n(g8u\n"); /* restore vertical position */ 199 lasty = savelasty; /* vertical position restored to where it was */ 200 lastx = xleft; /* before text, also horizontal is at left */ 201 } /* end HGPutText */ 202 203 204 /*----------------------------------------------------------------------------* 205 | Routine: doarc (center_point, start_point, angle) 206 | 207 | Results: produces either drawarc command or a drawcircle command 208 | depending on the angle needed to draw through. 209 *----------------------------------------------------------------------------*/ 210 211 doarc (cp, sp, angle) 212 POINT cp; 213 POINT sp; 214 int angle; 215 { 216 double radius = len(cp, sp); 217 double radians; 218 219 220 if (angle) { /* arc with angle */ 221 tmove (&sp); /* starting point first */ 222 printf("\\D'a"); 223 dx((double) cp.x); /* move to center */ 224 dy((double) cp.y); 225 226 radians = acos((sp.x - cp.x) / radius); /* angle of ending */ 227 if (cp.y - sp.y < 0.0) /* point calculated */ 228 radians = twopi - radians; /* from start point */ 229 radians += ((double) angle) * (pi / 180.0); /* and arc's angle */ 230 if (radians > twopi) radians -= twopi; 231 232 dx(cp.x + cos(radians) * radius); /* move to ending point */ 233 dy(cp.y - sin(radians) * radius); 234 235 } else { /* a full circle (angle == 0) */ 236 cp.x -= radius; 237 tmove(&cp); /* move to the left point first */ 238 /* draw circle with given diameter */ 239 printf("\\D'c %du", (int) ((radius + radius) * troffscale)); 240 } 241 putchar('\''); /* finish the command */ 242 cr(); 243 } 244 245 246 /*----------------------------------------------------------------------------* 247 | Routine: HGSetFont (font_number, Point_size) 248 | 249 | Results: ALWAYS outputs a .ft and .ps directive to troff. This is 250 | done because someone may change stuff inside a text string. 251 *----------------------------------------------------------------------------*/ 252 253 HGSetFont(font, size) 254 int font, size; 255 { 256 printf(".ft %s\n.ps %d\n", tfont[font-1], tsize[size-1]); 257 } 258 259 260 /*----------------------------------------------------------------------------* 261 | Routine: HGSetBrush (line_mode) 262 | 263 | Results: generates the troff commands to set up the line width and 264 | style of subsequent lines. Does nothing if no change is needed. 265 | 266 | Side Efct: sets "linmode" and "linethicknes" 267 *----------------------------------------------------------------------------*/ 268 269 HGSetBrush(mode) 270 int mode; 271 { 272 register int printed = 0; 273 274 if (linmod != style[--mode]) { 275 printf ("\\D's %du'", linmod = style[mode]); 276 printed = 1; 277 } 278 if (linethickness != thick[mode]) { 279 printf ("\\D't %du'", linethickness = thick[mode]); 280 printed = 1; 281 } 282 if (printed) 283 cr(); 284 } 285 286 287 /*----------------------------------------------------------------------------* 288 | Routine: dx (x_destination) 289 | 290 | Results: scales and outputs a number for delta x (with a leading space) 291 | given "lastx" and x_destination. 292 | 293 | Side Efct: resets "lastx" to x_destination. 294 *----------------------------------------------------------------------------*/ 295 296 dx(x) 297 double x; 298 { 299 register int ix = (int) (x * troffscale); 300 301 printf(" %du", ix - lastx); 302 lastx = ix; 303 } 304 305 306 /*----------------------------------------------------------------------------* 307 | Routine: dy (y_destination) 308 | 309 | Results: scales and outputs a number for delta y (with a leading space) 310 | given "lastyline" and y_destination. 311 | 312 | Side Efct: resets "lastyline" to y_destination. Since "line" vertical 313 | motions don't affect "page" ones, "lasty" isn't updated. 314 *----------------------------------------------------------------------------*/ 315 316 dy(y) 317 double y; 318 { 319 register int iy = (int) (y * troffscale); 320 321 printf(" %du", iy - lastyline); 322 lastyline = iy; 323 } 324 325 326 /*----------------------------------------------------------------------------* 327 | Routine: tmove (point_pointer) 328 | 329 | Results: produces horizontal and vertical moves for troff given the 330 | pointer of a point to move to and knowing the current position. 331 | Also puts out a horizontal move to start the line. 332 *----------------------------------------------------------------------------*/ 333 334 tmove(ptr) 335 POINT *ptr; 336 { 337 register int ix = (int) (ptr->x * troffscale); 338 register int iy = (int) (ptr->y * troffscale); 339 register int dx; 340 register int dy; 341 342 if (dy = iy - lasty) { 343 printf(".sp %du\n", dy); 344 } 345 lastyline = lasty = iy; /* lasty is always set to current */ 346 if (dx = ix - lastx) { 347 printf("\\h'%du'", dx); 348 lastx = ix; 349 } 350 } 351 352 353 /*----------------------------------------------------------------------------* 354 | Routine: cr ( ) 355 | 356 | Results: Ends off an input line. ".sp -1" is also added to counteract 357 | the vertical move done at the end of text lines. 358 | 359 | Side Efct: sets "lastx" to "xleft" for troff's return to left margin 360 *----------------------------------------------------------------------------*/ 361 362 cr() 363 { 364 printf("\n.sp -1\n"); 365 lastx = xleft; 366 } 367