summaryrefslogtreecommitdiff
path: root/dviware/dvitops/tpic.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvitops/tpic.c
Initial commit
Diffstat (limited to 'dviware/dvitops/tpic.c')
-rw-r--r--dviware/dvitops/tpic.c549
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:
+*/
+