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