1 /* hgraph.c 1.4 83/05/05
2 *
3 * Copyright -C- 1982 Barry S. Roitblat
4 *
5 * This file contains the graphics routines for hard copy (gprint)
6 * production of gremlin files.
7 *
8 */
9
10 #include "gprint.h"
11 #include <vfont.h>
12
13
14 /* line and character styles */
15
16 int style[STYLES] = { DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID };
17 int thick[STYLES] = { 1, 1, 5, 1, 1, 3 };
18 char *tfont[FONTS] = { "R", "I", "B", "S" };
19 char *tsize[SIZES] = { "10", "16", "24", "36" };
20
21
22 /* variables used to print from font file */
23
24 extern Orientation;
25 extern cfont;
26 extern csize;
27 extern struct header header;
28 extern struct dispatch dispatch[256];
29 extern char *bits;
30 extern char *fontdir ;
31
32 /* imports from main.c */
33
34 extern double scale;
35 extern point();
36 extern int linethickness;
37 extern int linmod;
38 extern int lastx;
39 extern int lasty;
40 extern double orgx;
41 extern double orgy;
42 extern int DevRange;
43
44
line(x0,y0,x1,y1)45 line(x0, y0, x1, y1)
46 int x0, y0, x1, y1;
47
48 /* This routine is called to draw a line from the point at (x0, y0) to (x1, y1).
49 * The line is drawn using a variation of
50 */
51
52 {
53 int dx, dy;
54 int xinc, yinc;
55 int res1;
56 int res2;
57 int slope;
58
59 xinc = 1;
60 yinc = 1;
61 if ((dx = x1-x0) < 0)
62 {
63 xinc = -1;
64 dx = -dx;
65 }
66 if ((dy = y1-y0) < 0)
67 {
68 yinc = -1;
69 dy = -dy;
70 }
71 slope = xinc*yinc;
72 res1 = 0;
73 res2 = 0;
74 if (dx >= dy)
75 while (x0 != x1)
76 {
77 if((x0+slope*y0)&linmod) point(x0, y0);
78 if (res1 > res2)
79 {
80 res2 += dx - res1;
81 res1 = 0;
82 y0 += yinc;
83 }
84 res1 += dy;
85 x0 += xinc;
86 }
87 else
88 while (y0 != y1)
89 {
90 if((x0+slope*y0)&linmod) point(x0, y0);
91 if (res1 > res2)
92 {
93 res2 += dy - res1;
94 res1 = 0;
95 x0 += xinc;
96 }
97 res1 += dx;
98 y0 += yinc;
99 }
100 if((x1+slope*y1)&linmod) point(x1, y1);
101 }
102
103
HGPrintElt(element)104 HGPrintElt(element)
105 ELT *element;
106
107 /* This routine examines the picture elements and calls the appropriate
108 * routine(s) to print them according to their type.
109 */
110
111 {
112 POINT *p1, *p2, pt1, pt2;
113 int x1, y1, i, dx, dy;
114 char *txt, c;
115
116 if ( !DBNullelt(element) )
117 {
118 if (TEXT(element->type))
119 {
120 p1 = element->ptlist;
121 HGSetFont(element->brushf, element->size);
122 pt1.x = mapx(xorn(p1->x, p1->y));
123 pt1.y = mapy(yorn(p1->x, p1->y));
124 txt = element->textpt;
125 HGPutText(element->type, pt1, txt);
126 }
127 else
128 {
129 switch (element->type)
130 {
131 case ARC: p1 = element->ptlist;
132 p2 = PTNextPoint(p1);
133 HGSetBrush(element->brushf);
134 pt1.x = mapx(xorn(p1->x, p1->y));
135 pt1.y = mapy(yorn(p1->x, p1->y));
136 pt2.x = mapx(xorn(p2->x, p2->y));
137 pt2.y = mapy(yorn(p2->x, p2->y));
138 HGArc(&pt1, &pt2, element->size);
139 break;
140
141 case CURVE: HGSetBrush(element->brushf);
142 HGCurve(element->ptlist);
143 break;
144
145 case VECTOR: p1 = element->ptlist;
146 p2 = PTNextPoint(p1);
147 HGSetBrush(element->brushf);
148 while ( !Nullpoint(p2) )
149 {
150 x1 = mapx(xorn(p1->x, p1->y));
151 y1 = mapy(yorn(p1->x, p1->y));
152 lastx = mapx(xorn(p2->x, p2->y));
153 lasty = mapy(yorn(p2->x, p2->y));
154 HGtline(x1, y1, lastx, lasty);
155 p1 = p2;
156 p2 = PTNextPoint(p2);
157 } /* end while */;
158 break;
159 } /* end switch */;
160 } /* end else Text */
161 } /* end if */
162 } /* end PrintElt */
163
164
HGPutText(justify,pnt,string)165 HGPutText(justify,pnt,string)
166 int justify;
167 POINT pnt;
168 char string[];
169
170 /* This routine is used to calculate the proper starting position for a
171 * text string (based on justification, size and font), and prints it
172 * character by character.
173 */
174
175 {
176 int length, height, nchars, i;
177 POINT pos;
178
179 height = dispatch['T'].up + dispatch['y'].down;
180 length = 0;
181 for (i=0; string[i] != '\0'; ++i)
182 length += dispatch[(string[i] == ' ') ? 'a' : string[i]].width;
183 nchars = i;
184 switch (justify)
185 {
186 case BOTLEFT: pos.x = pnt.x;
187 pos.y = pnt.y;
188 break;
189 case BOTCENT: if (Orientation == 0)
190 {
191 pos.x = pnt.x - (length/2);
192 pos.y = pnt.y;
193 }
194 else
195 {
196 pos.x = pnt.x;
197 pos.y = pnt.y - (length/2);
198 }
199 break;
200 case BOTRIGHT: if (Orientation == 0)
201 {
202 pos.x = pnt.x - length;
203 pos.y = pnt.y;
204 }
205 else
206 {
207 pos.x = pnt.x;
208 pos.y = pnt.y - length;
209 }
210 break;
211 case CENTLEFT: if (Orientation == 0)
212 {
213 pos.x = pnt.x;
214 pos.y = pnt.y + (height/2);
215 }
216 else
217 {
218 pos.x = pnt.x - (height/2);
219 pos.y = pnt.y;
220 }
221 break;
222 case CENTCENT: if (Orientation == 0)
223 {
224 pos.x = pnt.x - (length/2);
225 pos.y = pnt.y + (height/2);
226 }
227 else
228 {
229 pos.x = pnt.x - (height/2);
230 pos.y = pnt.y - (length/2);
231 }
232 break;
233 case CENTRIGHT: if (Orientation == 0)
234 {
235 pos.x = pnt.x - length;
236 pos.y = pnt.y + (height/2);
237 }
238 else
239 {
240 pos.x = pnt.x - (height/2);
241 pos.y = pnt.y - length;
242 }
243 break;
244 case TOPLEFT: if (Orientation == 0)
245 {
246 pos.x = pnt.x;
247 pos.y = pnt.y + height;
248
249 }
250 else
251 {
252 pos.x = pnt.x - height;
253 pos.y = pnt.y;
254 }
255 break;
256 case TOPCENT: if (Orientation == 0)
257 {
258 pos.x = pnt.x - (length/2);
259 pos.y = pnt.y + height;
260 }
261 else
262 {
263 pos.x = pnt.x - height;
264 pos.y = pnt.y - (length/2);
265 }
266 break;
267 case TOPRIGHT: if (Orientation == 0)
268 {
269 pos.x = pnt.x - length;
270 pos.y = pnt.y + height;
271 }
272 else
273 {
274 pos.x = pnt.x - height;
275 pos.y = pnt.y - length;
276 }
277 break;
278 }
279
280 HGMove(pos);
281 for ( i=0; i<nchars; ++i )
282 {
283 HGplotch(string[i]);
284 }
285 } /* end HGPutText */;
286
287
288 #define pi 3.14159265357
289 #define log2_10 3.321915
290
HGArc(center,cpoint,angle)291 HGArc(center,cpoint,angle)
292 POINT *center, *cpoint;
293 int angle;
294
295 /* This routine plots an arc centered about 'center' counter clockwise for
296 * the point 'cpoint' through 'angle' degrees. If angle is 0, a full circle
297 * is drawn.
298 */
299
300 {
301 double xs, ys, resolution, epsalon, degreesperpoint, fullcircle;
302 double t1, t2;
303 int i, extent, nx, ny;
304
305 xs = cpoint->x - center->x;
306 ys = cpoint->y - center->y;
307 lastx = (int) cpoint->x;
308 lasty = (int) cpoint->y;
309
310 /* calculate drawing parameters */
311
312 t1 = log10(sqrt( xs * xs + ys * ys)) * log2_10;
313 t1 = ceil(t1);
314 resolution = pow(2.0, t1);
315 epsalon = 1.0 / resolution;
316 fullcircle = 2 * pi * resolution;
317 fullcircle = ceil(fullcircle);
318 degreesperpoint = 360.0 / fullcircle;
319
320 if (angle == 0) extent = fullcircle;
321 else extent = angle/degreesperpoint;
322
323 for (i=0; i<extent; ++i)
324 {
325 xs += epsalon * ys;
326 nx = (int) (xs + center->x + 0.5);
327 ys -= epsalon * xs;
328 ny = (int) (ys + center->y + 0.5);
329 RoundEnd(nx, ny, (int) (linethickness/2), FALSE);
330 lastx = nx;
331 lasty = ny;
332 } /* end for */;
333 } /* end HGArc */;
334
335
RoundEnd(x,y,radius,filled)336 RoundEnd(x, y, radius, filled)
337 int x, y, radius;
338 int filled; /* indicates whether the circle is filled */
339
340 /* This routine plots a filled circle of the specified radius centered
341 * about (x, y).
342 */
343
344 {
345 double xs, ys, epsalon;
346 int i, j, k, extent, nx, ny;
347 int cx, cy;
348
349 if (radius < 1) /* too small to notice */
350 {
351 point(x, y);
352 return;
353 }
354 xs = 0;
355 ys = radius;
356 epsalon = 1.0 / radius;
357 extent = pi * radius / 2; /* 1/4 the circumference */
358
359 /* Calculate the trajectory of the circle for 1/4 the circumference
360 * and mirror appropriately to get the other three quadrants.
361 */
362
363 point(x, y+((int) ys)); /* take care if end of arc missed by */
364 point(x, y-((int) ys)); /* below formulation */
365 for (i=0; i<extent; ++i)
366 {
367 /* generate circumference */
368 xs += epsalon * ys;
369 nx = (int) (xs + x + 0.5);
370 if (nx < x) nx = x; /* 1st quadrant, should be positive */
371 ys -= epsalon * xs;
372 ny = (int) (ys + y + 0.5);
373 if (ny < y) ny = y; /* 1st quadrant, should be positive */
374
375 if (filled == TRUE)
376 { /* fill from center */
377 cx = x;
378 cy = y;
379 }
380 else
381 { /* fill from perimeter only (no fill) */
382 cx = nx;
383 cy = ny;
384 }
385 for (j=cx; j<=nx; ++j)
386 {
387 for (k=cy; k<=ny; ++k)
388 {
389 point(j, k);
390 point(j, 2*y-k);
391 point(2*x-j, k);
392 point(2*x-j, 2*y-k);
393 } /* end for k */
394 } /* end for j */;
395 } /* end for i */;
396 } /* end RoundEnd */;
397
398
399 #define MAXPOINTS 200
400
Paramaterize(x,y,h,n)401 static Paramaterize(x, y, h, n)
402 float x[MAXPOINTS], y[MAXPOINTS], h[MAXPOINTS];
403 int n;
404 /* This routine calculates parameteric values for use in calculating
405 * curves. The parametric values are returned in the array u. The values
406 * are an approximation of cumulative arc lengths of the curve (uses cord
407 * length). For additional information, see paper cited below.
408 */
409
410 {
411 int i,j;
412 float u[MAXPOINTS];
413
414 for (i=1; i<=n; ++i)
415 {
416 u[i] = 0;
417 for (j=1; j<i; ++j)
418 {
419 u[i] += sqrt(pow((double) (x[j+1] - x[j]),(double) 2.0)
420 + pow((double) (y[j+1] - y[j]), (double) 2.0));
421 }
422 }
423 for (i=1; i<n; ++i)
424 h[i] = u[i+1] - u[i];
425 } /* end Paramaterize */
426
PeriodicSpline(h,z,dz,d2z,d3z,npoints)427 static PeriodicSpline(h, z, dz, d2z, d3z, npoints)
428 float h[MAXPOINTS], z[MAXPOINTS]; /* Point list and paramaterization */
429 float dz[MAXPOINTS]; /* to return the 1st derivative */
430 float d2z[MAXPOINTS], d3z[MAXPOINTS]; /* 2nd and 3rd derivatives */
431 int npoints; /* number of valid points */
432 /*
433 * This routine solves for the cubic polynomial to fit a spline
434 * curve to the the points specified by the list of values.
435 * The Curve generated is periodic. The alogrithms for this
436 * curve are from the "Spline Curve Techniques" paper cited below.
437 */
438
439 {
440 float d[MAXPOINTS];
441 float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
442 float c[MAXPOINTS], r[MAXPOINTS], s[MAXPOINTS];
443 int i;
444
445 /* step 1 */
446 for (i=1; i<npoints; ++i)
447 {
448 if (h[i] != 0)
449 deltaz[i] = (z[i+1] - z[i]) / h[i];
450 else
451 deltaz[i] = 0;
452 }
453 h[0] = h[npoints-1];
454 deltaz[0] = deltaz[npoints-1];
455
456 /* step 2 */
457 for (i=1; i<npoints-1; ++i)
458 {
459 d[i] = deltaz[i+1] - deltaz[i];
460 }
461 d[0] = deltaz[1] - deltaz[0];
462
463 /* step 3a */
464 a[1] = 2 * (h[0] + h[1]);
465 b[1] = d[0];
466 c[1] = h[0];
467 for (i=2; i<npoints-1; ++i)
468 {
469 a[i] = 2 * (h[i-1] + h[i]) - pow((double) h[i-1], (double) 2.0)
470 / a[i-1];
471 b[i] = d[i-1] - h[i-1] * b[i-1]/a[i-1];
472 c[i] = -h[i-1] * c[i-1]/a[i-1];
473 }
474
475 /* step 3b */
476 r[npoints-1] = 1;
477 s[npoints-1] = 0;
478 for (i=npoints-2; i>0; --i)
479 {
480 r[i] = -(h[i] * r[i+1] + c[i])/a[i];
481 s[i] = (6 * b[i] - h[i] * s[i+1])/a[i];
482 }
483
484 /* step 4 */
485 d2z[npoints-1] = (6 * d[npoints-2] - h[0] * s[1]
486 - h[npoints-1] * s[npoints-2])
487 / (h[0] * r[1] + h[npoints-1] * r[npoints-2]
488 + 2 * (h[npoints-2] + h[0]));
489 for (i=1; i<npoints-1; ++i)
490 {
491 d2z[i] = r[i] * d2z[npoints-1] + s[i];
492 }
493 d2z[npoints] = d2z[1];
494
495 /* step 5 */
496 for (i=1; i<npoints; ++i)
497 {
498 dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i+1])/6;
499 if (h[i] != 0)
500 d3z[i] = (d2z[i+1] - d2z[i])/h[i];
501 else
502 d3z[i] = 0;
503 }
504 } /* end PeriodicSpline */
505
506
NaturalEndSpline(h,z,dz,d2z,d3z,npoints)507 static NaturalEndSpline(h, z, dz, d2z, d3z, npoints)
508 float h[MAXPOINTS], z[MAXPOINTS]; /* Point list and parameterization */
509 float dz[MAXPOINTS]; /* to return the 1st derivative */
510 float d2z[MAXPOINTS], d3z[MAXPOINTS]; /* 2nd and 3rd derivatives */
511 int npoints; /* number of valid points */
512 /*
513 * This routine solves for the cubic polynomial to fit a spline
514 * curve the the points specified by the list of values. The alogrithms for
515 * this curve are from the "Spline Curve Techniques" paper cited below.
516 */
517
518 {
519 float d[MAXPOINTS];
520 float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
521 int i;
522
523 /* step 1 */
524 for (i=1; i<npoints; ++i)
525 {
526 if (h[i] != 0)
527 deltaz[i] = (z[i+1] - z[i]) / h[i];
528 else
529 deltaz[i] = 0;
530 }
531 deltaz[0] = deltaz[npoints-1];
532
533 /* step 2 */
534 for (i=1; i<npoints-1; ++i)
535 {
536 d[i] = deltaz[i+1] - deltaz[i];
537 }
538 d[0] = deltaz[1] - deltaz[0];
539
540 /* step 3 */
541 a[0] = 2 * (h[2] + h[1]);
542 b[0] = d[1];
543 for (i=1; i<npoints-2; ++i)
544 {
545 a[i] = 2 * (h[i+1] + h[i+2]) - pow((double) h[i+1],(double) 2.0)
546 / a[i-1];
547 b[i] = d[i+1] - h[i+1] * b[i-1]/a[i-1];
548 }
549
550 /* step 4 */
551 d2z[npoints] = d2z[1] = 0;
552 for (i=npoints-1; i>1; --i)
553 {
554 d2z[i] = (6 * b[i-2] - h[i] *d2z[i+1])/a[i-2];
555 }
556
557 /* step 5 */
558 for (i=1; i<npoints; ++i)
559 {
560 dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i+1])/6;
561 if (h[i] != 0)
562 d3z[i] = (d2z[i+1] - d2z[i])/h[i];
563 else
564 d3z[i] = 0;
565 }
566 } /* end NaturalEndSpline */
567
568
569 #define PointsPerInterval 32
570
HGCurve(pointlist,style)571 HGCurve(pointlist,style)
572 POINT *pointlist;
573 int style;
574 /*
575 * This routine generates a smooth curve through a set of points. The
576 * method used is the parametric spline curve on unit knot mesh described
577 * in "Spline Curve Techniques" by Patrick Baudelaire, Robert Flegal, and
578 * Robert Sproull -- Xerox Parc.
579 */
580 {
581 float h[MAXPOINTS];
582 float x[MAXPOINTS], y[MAXPOINTS], dx[MAXPOINTS], dy[MAXPOINTS];
583 float d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], d3y[MAXPOINTS];
584 float t, t2, t3, xinter, yinter;
585 POINT *ptr;
586 int numpoints, i, j, k, lx, ly, nx, ny;
587
588 /* Copy point list to array for easier access */
589
590 ptr = pointlist;
591 for (i=1; (!Nullpoint(ptr)); ++i)
592 {
593 x[i] = mapx(xorn(ptr->x, ptr->y));
594 y[i] = mapy(yorn(ptr->x, ptr->y));
595 if (i >= MAXPOINTS - 1) break;
596 ptr = PTNextPoint(ptr);
597 }
598 lx = (int) x[1];
599 ly = (int) y[1];
600
601 /* Solve for derivatives of the curve at each point
602 * separately for x and y (parametric).
603 */
604 numpoints = i - 1;
605 Paramaterize(x, y, h, numpoints);
606 if ((x[1] == x[numpoints]) && (y[1] == y[numpoints]))/* closed curve */
607 {
608 PeriodicSpline(h, x, dx, d2x, d3x, numpoints);
609 PeriodicSpline(h, y, dy, d2y, d3y, numpoints);
610 }
611 else
612 {
613 NaturalEndSpline(h, x, dx, d2x, d3x, numpoints);
614 NaturalEndSpline(h, y, dy, d2y, d3y, numpoints);
615 }
616
617 /* generate the curve using the above information and
618 * PointsPerInterval vectors between each specified knot.
619 */
620
621 for (j=1; j<numpoints; ++j)
622 {
623 if ((x[j] == x[j+1]) && (y[j] == y[j+1])) continue;
624 for (k=0; k<=PointsPerInterval; ++k)
625 {
626 t = (float) k * h[j] / (float) PointsPerInterval;
627 t2 = t * t;
628 t3 = t * t * t;
629 xinter = x[j] + t * dx[j] + t2 * d2x[j]/2
630 + t3 * d3x[j]/6;
631 nx = (int) xinter;
632 yinter = y[j] + t * dy[j] + t2 * d2y[j]/2
633 + t3 * d3y[j]/6;
634 ny = (int) yinter;
635 HGtline(lx, ly, nx, ny);
636 lx = nx;
637 ly = ny;
638 } /* end for k */
639 } /* end for j */
640 } /* end HGCurve */
641
642
643
HGplotch(ch)644 HGplotch(ch)
645 char ch;
646
647 /* This routine prints a single character using the current (bit mapped)
648 * vtroff font
649 */
650
651 {
652 int i,j,k;
653 char *ptr,c;
654 int nbytes;
655
656 ptr = bits + dispatch[ch].addr;
657
658 for(i = dispatch[ch].up; i > -dispatch[ch].down; --i)
659 {
660 nbytes = (dispatch[ch].right + dispatch[ch].left + 7)/8;
661 for(j = 0; j < nbytes; j++)
662 {
663 c = *ptr++;
664 for(k=7; k>=0; --k)
665 if((c>>k) & 1)
666 if (Orientation == 0 )
667 point(lastx+7-k+j*8-dispatch[ch].left, lasty-i);
668 else
669 point(lastx+i, lasty+7-k+j*8-dispatch[ch].left);
670 }
671 }
672 if (Orientation == 0)
673 lastx += dispatch[ (ch == ' ') ? 'a' : ch ].width;
674 else
675 lasty += dispatch[ (ch == ' ') ? 'a' : ch ].width;
676 }
677
678
HGInitFont(fontFile)679 HGInitFont(fontFile)
680 char *fontFile;
681
682 /* This routine reads in the appropriate font file */
683
684 {
685 char *s;
686 int fonts;
687 int i;
688
689 /* Get the font file */
690 s = fontFile;
691 if((fonts = open(s,0)) == -1)
692 {
693 perror(s);
694 fprintf(stderr,"Can't get font file\n");
695 exit(1);
696 }
697 /* Get the header and check magic number */
698 if(read(fonts,&header,sizeof(header)) != sizeof(header))
699 {
700 perror(s);
701 fprintf(stderr,"Bad read in font file\n");
702 exit(1);
703 }
704 if(header.magic != 0436)
705 {
706 fprintf(stderr,"Bad magic numer in font file\n");
707 exit(1);
708 }
709 /* Get dispatches */
710 if(read(fonts,dispatch,sizeof(dispatch)) != sizeof(dispatch))
711 {
712 perror(s);
713 fprintf(stderr,"Bad read in font file\n");
714 exit(1);
715 }
716 /* Allocate space for bit map and read in bits */
717 if (bits != NULL) free(bits);
718 bits = (char *) malloc(header.size);
719
720 if(read(fonts,bits,header.size) != header.size)
721 {
722 perror(s);
723 fprintf(stderr,"Can't read bit map in font file\n");
724 exit(1);
725 }
726 /* Close font file */
727 if(close(fonts) != 0)
728 {
729 perror(s);
730 fprintf(stderr,"Can't close font file\n");
731 exit(1);
732 }
733 }
734
735
HGtline(x0,y0,x1,y1)736 HGtline(x0, y0, x1, y1)
737 int x0, y0, x1, y1;
738 /*
739 * This routine calls line repeatedly until the line is
740 * of the proper thickness.
741 */
742
743 {
744 double morelen, theta, wx, wy, xx, xy;
745 int xs, xe, ys, ye;
746 int addln, j, xdir, ydir, dx, dy;
747
748 xdir = ydir = 1;
749 dx = x1 - x0; /* calculate direction to move to */
750 dy = y1 - y0; /* move to draw additional lines if needed */
751 if (dx < 0 ) /* for extra thickness */
752 {
753 dx = -dx;
754 xdir = -1;
755 }
756 if (dy < 0 )
757 {
758 dy = -dy;
759 ydir = -1;
760 }
761
762 morelen = linethickness / 2;
763 addln = (int) morelen;
764 RoundEnd(x0, y0, (int) morelen, TRUE); /* add rounded end */
765 for (j=(-addln); j<=addln; ++j)
766 {
767 if (dy == 0)
768 {
769 xs = x0;
770 xe = x1;
771 ys = ye = y0 + j;
772 }
773 if (dx == 0)
774 {
775 ys = y0;
776 ye = y1;
777 xs = xe = x0 + j;
778 }
779 if ((dx != 0) && (dy != 0))
780 {
781 theta = pi / 2.0 - atan( ((double) dx)/((double) dy) );
782 wx = j * sin(theta);
783 wy = j * cos(theta);
784 xs = x0 + wx * xdir;
785 ys = y0 - wy * ydir;
786 xe = x1 + wx * xdir;
787 ye = y1 - wy * ydir;
788 }
789 line(xs, ys, xe, ye);
790 } /* end for */
791 RoundEnd(x1, y1, (int) morelen, TRUE); /* add rounded end */
792 } /* end HGtline */
793
794
HGMove(p)795 HGMove(p)
796 POINT p;
797 {
798 lastx = p.x;
799 lasty = p.y;
800 }
801
HGSetFont(font,size)802 HGSetFont(font, size)
803 int font, size;
804 {
805 int i;
806 char c, string[100];
807
808 if ((font == cfont) && (size == csize)) return;
809 cfont = font;
810 csize = size;
811 strcpy(string, fontdir);
812 strcat(string, tfont[font-1]);
813 strcat(string, ".");
814 strcat(string, tsize[size-1]);
815 HGInitFont(string);
816 }
817
HGSetBrush(mode)818 HGSetBrush(mode)
819 int mode;
820 {
821 linmod = style[mode - 1];
822 linethickness = thick[mode - 1];
823
824 }
825