diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvitops/tpic.c |
Initial commit
Diffstat (limited to 'dviware/dvitops/tpic.c')
-rw-r--r-- | dviware/dvitops/tpic.c | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/dviware/dvitops/tpic.c b/dviware/dvitops/tpic.c new file mode 100644 index 0000000000..1700354b96 --- /dev/null +++ b/dviware/dvitops/tpic.c @@ -0,0 +1,549 @@ +static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/tpic.c,v 1.4 90/08/14 13:03:50 jjc Rel $"; + +#include "dvitops.h" + +#ifdef TPIC_SUPPORT + +/* Dotted lines look a bit anaemic; so we add this many milli-inches to + the pen size of a dotted line. */ + +#define DOTTED_LINE_WIDTH_ADDITION 3 + +/* flags in tpic_object is or'ed from these */ + +#define ARC 1 +#define SPLINE 2 +#define SHADED 4 +#define INVISIBLE 8 +#define DOTTED 16 +#define DASHED 32 + +struct point { + integer x; + integer y; +}; + +struct tpic_object { + struct tpic_object *next; + integer h, v; + int region; + unsigned flags; + integer pen_size; + float shade; + union { + struct { + float dash_width; + int npoints; + struct point point_vector[2]; /* may be bigger than this */ + } p; + struct { + integer cx; + integer cy; + integer rx; + integer ry; + float s; + float e; + } a; + } u; +}; + +#ifdef PROTO +static void draw_path(FILE *psfp, double sc, integer h, integer v, + struct point *pv, int np, int closed); +static void draw_spline(FILE *psfp, double sc, integer h, integer v, + struct point *pv, int np); +static void draw_ellipse(FILE *psfp, double sc, integer h, integer v, + integer cx, integer cy, integer rx, integer ry); +static void draw_arc(FILE *psfp, double sc, integer h, integer v, + integer cx, integer cy, integer r, double s, double e); +#else +static void draw_path(); +static void draw_spline(); +static void draw_ellipse(); +static void draw_arc(); +#endif + +struct tpic_object *tpic_object_list = NULL; + +#define TPIC_CODE(c1, c2) (((unsigned char)(c1) << 8) + (unsigned char)(c2)) + +/* return 1 if it was a tpic_special, 0 otherwise */ + +int tpic_special(pass, arg, x, y) +int pass; +char *arg; +integer x, y; +{ + static integer current_pen_size = 8; + static unsigned tpic_flags = 0; + static float shade = 0.0; + static int npoints = 0; + static int maxpoints = 0; + static struct point *point_vector = 0; + double dash_width; + int complete = 0; + while (*arg == ' ') + arg++; + if (arg[0] == '\0' || arg[1] == '\0' + || (arg[2] != ' ' && arg[2] != '\0')) + return 0; + if (pass != PASS2) { + switch (TPIC_CODE(arg[0], arg[1])) { + case TPIC_CODE('p', 'n'): + case TPIC_CODE('p', 'a'): + case TPIC_CODE('s', 'p'): + case TPIC_CODE('d', 'a'): + case TPIC_CODE('d', 't'): + case TPIC_CODE('i', 'p'): + case TPIC_CODE('f', 'p'): + case TPIC_CODE('i', 'a'): + case TPIC_CODE('a', 'r'): + case TPIC_CODE('s', 'h'): + case TPIC_CODE('w', 'h'): + case TPIC_CODE('b', 'k'): + return 1; + default: + /* it's not a tpic special */ + return 0; + } + } + switch (TPIC_CODE(arg[0], arg[1])) { + case TPIC_CODE('p', 'n'): + { + long n; + if (sscanf(arg + 2, "%ld", &n) != 1) { + message(ERROR, "bad argument to pn special"); + return 1; + } + current_pen_size = n; + break; + } + case TPIC_CODE('p', 'a'): + { + long x, y; + if (sscanf(arg + 2, "%ld %ld", &x, &y) != 2) { + message(ERROR, "bad arguments to pa special"); + return 1; + } + if (npoints >= maxpoints) { + if (maxpoints == 0) { + point_vector = (struct point *) + malloc((maxpoints = 5)*sizeof(struct point)); + if (point_vector == NULL) + out_of_memory(); + } + else { + point_vector = (struct point *) + realloc((char *)point_vector, + sizeof(struct point)*(maxpoints *= 2)); + if (point_vector == NULL) + out_of_memory(); + } + } + point_vector[npoints].x = x; + point_vector[npoints].y = y; + npoints++; + break; + } + case TPIC_CODE('s', 'p'): + { + float f; + if (sscanf(arg + 2, "%f", &f) == 1 && f != 0.0) { + if (f > 0.0) { + tpic_flags |= DASHED; + dash_width = f; + } + else { + tpic_flags |= DOTTED; + dash_width = -f; + } + } + tpic_flags |= SPLINE; + goto path; + } + case TPIC_CODE('d', 'a'): + { + float f; + if (sscanf(arg + 2, "%f", &f) != 1) { + message(ERROR, "bad argument to da special"); + return 1; + } + tpic_flags |= DASHED; + dash_width = f; + goto path; + } + case TPIC_CODE('d', 't'): + { + float f; + if (sscanf(arg + 2, "%f", &f) != 1) { + message(ERROR, "bad argument to dt special"); + return 1; + } + tpic_flags |= DOTTED; + dash_width = f; + goto path; + } + case TPIC_CODE('i', 'p'): + tpic_flags |= INVISIBLE; + /* fall through */ + case TPIC_CODE('f', 'p'): + path: + { + struct tpic_object *p; + size_t sz = sizeof(struct tpic_object); + if (npoints > 2) + sz += sizeof(struct point)*(npoints - 2); + p = (struct tpic_object *)malloc(sz); + if (p == NULL) + out_of_memory(); + p->flags = tpic_flags; + if (tpic_flags & (DOTTED|DASHED)) + p->u.p.dash_width = dash_width; + tpic_flags = 0; + memcpy((char *)p->u.p.point_vector, (char *)point_vector, + npoints*sizeof(struct point)); + p->u.p.npoints = npoints; + npoints = 0; + p->next = tpic_object_list; + tpic_object_list = p; + complete = 1; + break; + } + case TPIC_CODE('i', 'a'): + tpic_flags |= INVISIBLE; + /* fall through */ + case TPIC_CODE('a', 'r'): + { + struct tpic_object *p; + long x, y; + long rx, ry; + float s, e; + if (sscanf(arg + 2, "%ld %ld %ld %ld %f %f", + &x, &y, &rx, &ry, &s, &e) != 6) { + if (arg[0] == 'i') + message(ERROR, "bad argument to ia special"); + else + message(ERROR, "bad argument to ar special"); + return 1; + } + p = (struct tpic_object *)malloc(sizeof(struct tpic_object)); + if (p == NULL) + out_of_memory(); + p->flags = ARC|tpic_flags; + tpic_flags = 0; + p->u.a.cx = x; + p->u.a.cy = y; + p->u.a.rx = rx; + p->u.a.ry = ry; + p->u.a.s = s; + p->u.a.e = e; + p->next = tpic_object_list; + tpic_object_list = p; + complete = 1; + break; + } + case TPIC_CODE('s', 'h'): + { + float f; + if (sscanf(arg + 2, "%f", &f) != 1) + f = 0.5; + tpic_flags |= SHADED; + shade = f; + break; + } + case TPIC_CODE('w', 'h'): + tpic_flags |= SHADED; + shade = 0.0; + break; + case TPIC_CODE('b', 'k'): + tpic_flags |= SHADED; + shade = 1.0; + break; + default: + /* it's not a tpic special */ + return 0; + } + if (complete) { + /* we just completed an object, so fill in some details */ + tpic_object_list->h = x; + tpic_object_list->v = y; + tpic_object_list->region = current_region; + tpic_object_list->pen_size = current_pen_size; + if (tpic_object_list->flags & DOTTED) + tpic_object_list->pen_size += DOTTED_LINE_WIDTH_ADDITION; + if (tpic_object_list->flags & SHADED) + tpic_object_list->shade = shade; + } + return 1; +} + +#define round(d) ((long)((d) + 0.5)) + + +void p_tpic_list(psfp, page) +FILE *psfp; +struct page_info *page; +{ + int r = NO_REGION; + integer ox = 0, oy = 0; + integer ps = -1; + double sc = (254.0*page->den)/page->num; + struct tpic_object *p = tpic_object_list; + if (p == NULL) + return; + /* reverse tpic_object_list */ + tpic_object_list = NULL; + while (p != NULL) { + struct tpic_object *tem = p; + p = p->next; + tem->next = tpic_object_list; + tpic_object_list = tem; + } + fputs("BO TP\n", psfp); + while (tpic_object_list != NULL) { + p = tpic_object_list; + if (p->region != r) { + if (r != NO_REGION) + fputs("GR\n", psfp); + if (p->region != NO_REGION) { + fputs("GS\n", psfp); + do_transform(p->region, &ox, &oy, psfp); + } + else + ox = oy = 0; + r = p->region; + } + p->h -= ox; + p->v -= oy; + if (p->pen_size != ps) { + ps = p->pen_size; + put_dim(round(ps*sc), psfp); + fputs(" LW\n", psfp); + } + if (p->flags & ARC) { + integer cx, cy, rx, ry; + double s, e; + cx = p->u.a.cx; + cy = p->u.a.cy; + rx = p->u.a.rx; + ry = p->u.a.ry; + s = p->u.a.s; + e = p->u.a.e; + if (e - s >= M_PI*2.0) { + if (p->flags & SHADED) { + if (p->shade != 1.0) + fprintf(psfp, "%g SG\n", 1 - p->shade); + draw_ellipse(psfp, sc, p->h, p->v, cx, cy, rx, ry); + fputs("FI\n", psfp); + if (p->shade != 1.0) + fputs("0 SG\n", psfp); + } + if (!(p->flags & INVISIBLE)) { + draw_ellipse(psfp, sc, p->h, p->v, cx, cy, rx, ry); + fputs("ST\n", psfp); + } + } + else { + if (rx != ry) + message(WARNING, "open arc with rx != ry"); + draw_arc(psfp, sc, p->h, p->v, cx, cy, rx, s, e); + fputs("ST\n", psfp); + } + } + else { + int np = p->u.p.npoints; + struct point *pv = p->u.p.point_vector; + double dw = p->u.p.dash_width*1000.0; + if (p->flags & SPLINE) { + if (p->flags & DASHED) { + put_dim(round(sc*dw), psfp); + putc(' ', psfp); + put_dim(round(sc*dw), psfp); + fputs(" DH\n", psfp); + } + else if (p->flags & DOTTED) { + fputs("0 ", psfp); + put_dim(round(sc*dw), psfp); + fputs(" DH\n", psfp); + } + draw_spline(psfp, sc, p->h, p->v, pv, np); + fputs("ST\n", psfp); + if (p->flags & (DOTTED|DASHED)) + fputs("SO\n", psfp); + } + else { + int closed = (np >= 2 + && pv[0].x == pv[np - 1].x + && pv[0].y == pv[np - 1].y); + if (p->flags & SHADED) { + if (p->shade != 1.0) + fprintf(psfp, "%g SG\n", 1 - p->shade); + draw_path(psfp, sc, p->h, p->v, pv, np - (closed != 0), 1); + fputs("FI\n", psfp); + if (p->shade != 1.0) + fputs("0 SG\n", psfp); + } + if (!(p->flags & INVISIBLE)) { + if (p->flags & DOTTED) { + int i; + for (i = 0; i < np - 1; i++) { + double x = pv[i+1].x - pv[i].x; + double y = pv[i+1].y - pv[i].y; + double dist = sqrt(x*x + y*y); + double adw; + if (dist <= dw) + adw = dist; + else + adw = dist/round(dist/dw); + fputs("0 ", psfp); + put_dim(round(sc*adw), psfp); + fputs(" DH\n", psfp); + draw_path(psfp, sc, p->h, p->v, pv + i, 2, 0); + fputs("ST\n", psfp); + } + fputs("SO\n", psfp); + } + else if (p->flags & DASHED) { + int i; + for (i = 0; i < np - 1; i++) { + double x = pv[i+1].x - pv[i].x; + double y = pv[i+1].y - pv[i].y; + double dist = sqrt(x*x + y*y); + double adw, gw; + if (dist <= dw*2.0) { + adw = dist; + gw = 0.0; + } + else { + int ndashes = (int)(ceil((dist - dw)/(dw*2.0))); + gw = (dist - dw)/ndashes - dw; + adw = dw; + } + put_dim(round(sc*adw), psfp); + putc(' ', psfp); + put_dim(round(sc*gw), psfp); + fputs(" DH\n", psfp); + draw_path(psfp, sc, p->h, p->v, pv + i, 2, 0); + fputs("ST\n", psfp); + } + fputs("SO\n", psfp); + } + else { + draw_path(psfp, sc, p->h, p->v, pv, + np - (closed != 0), closed); + fputs("ST\n", psfp); + } + } + } + } + tpic_object_list = tpic_object_list->next; + free((char *)p); + } + if (r != NO_REGION) + fputs("GR\n", psfp); + fputs("EO\n", psfp); +} + +static void draw_path(psfp, sc, ox, oy, pv, np, closed) +FILE *psfp; +double sc; +integer ox, oy; +struct point *pv; +int np; +int closed; +{ + int i; + put_dim(ox + round(pv[0].x*sc), psfp); + putc(' ', psfp); + put_dim(oy + round(pv[0].y*sc), psfp); + fputs(" MT\n", psfp); + for (i = 1; i < np; i++) { + put_dim(ox + round(pv[i].x*sc), psfp); + putc(' ', psfp); + put_dim(oy + round(pv[i].y*sc), psfp); + fputs(" LT\n", psfp); + } + if (closed) + fputs("CP\n", psfp); +} + +static void draw_spline(psfp, sc, ox, oy, pv, np) +FILE *psfp; +double sc; +integer ox, oy; +struct point *pv; +int np; +{ + int i; + put_dim(ox + round(pv[0].x*sc), psfp); + putc(' ', psfp); + put_dim(oy + round(pv[0].y*sc), psfp); + fputs(" MT\n", psfp); + put_dim(ox + round((pv[0].x+pv[1].x)*sc/2.0), psfp); + putc(' ', psfp); + put_dim(oy + round((pv[0].y+pv[1].y)*sc/2.0), psfp); + fputs(" LT\n", psfp); + for (i = 1; i < np - 1; i++) { + put_dim(ox + round((pv[i-1].x + 5*pv[i].x)*sc/6.0), psfp); + putc(' ', psfp); + put_dim(oy + round((pv[i-1].y + 5*pv[i].y)*sc/6.0), psfp); + putc(' ', psfp); + put_dim(ox + round((5*pv[i].x + pv[i+1].x)*sc/6.0), psfp); + putc(' ', psfp); + put_dim(oy + round((5*pv[i].y + pv[i+1].y)*sc/6.0), psfp); + putc(' ', psfp); + put_dim(ox + round((pv[i].x+pv[i+1].x)*sc/2.0), psfp); + putc(' ', psfp); + put_dim(oy + round((pv[i].y+pv[i+1].y)*sc/2.0), psfp); + fputs(" CT\n", psfp); + } + put_dim(ox + round(pv[np - 1].x*sc), psfp); + putc(' ', psfp); + put_dim(oy + round(pv[np - 1].y*sc), psfp); + fputs(" LT\n", psfp); +} + +static void draw_ellipse(psfp, sc, ox, oy, cx, cy, rx, ry) +FILE *psfp; +double sc; +integer ox, oy; +integer cx, cy, rx, ry; +{ + put_dim(round(rx*sc), psfp); + putc(' ', psfp); + put_dim(round(ry*sc), psfp); + putc(' ', psfp); + put_dim(ox + round(sc*cx), psfp); + putc(' ', psfp); + put_dim(oy + round(sc*cy), psfp); + fputs(" EL\n", psfp); +} + +static void draw_arc(psfp, sc, ox, oy, cx, cy, r, s, e) +FILE *psfp; +double sc; +integer ox, oy; +integer cx, cy, r; +double s, e; +{ + put_dim(ox + round(sc*cx), psfp); + putc(' ', psfp); + put_dim(oy + round(sc*cy), psfp); + putc(' ', psfp); + put_dim(round(sc*r), psfp); + fprintf(psfp, " %g %g AR\n", s*180.0/M_PI, e*180.0/M_PI); +} + +#endif + +/* +Local Variables: +c-indent-level: 4 +c-continued-statement-offset: 4 +c-brace-offset: -4 +c-argdecl-indent: 0 +c-label-offset: -4 +tab-width: 4 +End: +*/ + |