void ps_printer::draw(int code, int *p, int np, const environment *env) { if (invis_count > 0) return; flush_sbuf(); int fill_flag = 0; switch (code) { case 'C': fill_flag = 1; // fall through case 'c': // troff adds an extra argument to C if (np != 1 && !(code == 'C' && np == 2)) { error("1 argument required for circle"); break; } out.put_fix_number(env->hpos + p[0]/2) .put_fix_number(env->vpos) .put_fix_number(p[0]/2) .put_symbol("DC"); if (fill_flag) fill_path(env); else { set_line_thickness_and_color(env); out.put_symbol("ST"); } break; case 'l': if (np != 2) { error("2 arguments required for line"); break; } set_line_thickness_and_color(env); out.put_fix_number(p[0] + env->hpos) .put_fix_number(p[1] + env->vpos) .put_fix_number(env->hpos) .put_fix_number(env->vpos) .put_symbol("DL"); break; case 'E': fill_flag = 1; // fall through case 'e': if (np != 2) { error("2 arguments required for ellipse"); break; } out.put_fix_number(p[0]) .put_fix_number(p[1]) .put_fix_number(env->hpos + p[0]/2) .put_fix_number(env->vpos) .put_symbol("DE"); if (fill_flag) fill_path(env); else { set_line_thickness_and_color(env); out.put_symbol("ST"); } break; case 'P': fill_flag = 1; // fall through case 'p': { if (np & 1) { error("even number of arguments required for polygon"); break; } if (np == 0) { error("no arguments for polygon"); break; } out.put_fix_number(env->hpos) .put_fix_number(env->vpos) .put_symbol("MT"); for (int i = 0; i < np; i += 2) out.put_fix_number(p[i]) .put_fix_number(p[i+1]) .put_symbol("RL"); out.put_symbol("CL"); if (fill_flag) fill_path(env); else { set_line_thickness_and_color(env); out.put_symbol("ST"); } break; } case '~': { if (np & 1) { error("even number of arguments required for spline"); break; } if (np == 0) { error("no arguments for spline"); break; } out.put_fix_number(env->hpos) .put_fix_number(env->vpos) .put_symbol("MT"); out.put_fix_number(p[0]/2) .put_fix_number(p[1]/2) .put_symbol("RL"); /* tnum/tden should be between 0 and 1; the closer it is to 1 the tighter the curve will be to the guiding lines; 2/3 is the standard value */ const int tnum = 2; const int tden = 3; for (int i = 0; i < np - 2; i += 2) { out.put_fix_number((p[i]*tnum)/(2*tden)) .put_fix_number((p[i + 1]*tnum)/(2*tden)) .put_fix_number(p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden)) .put_fix_number(p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden)) .put_fix_number((p[i] - p[i]/2) + p[i + 2]/2) .put_fix_number((p[i + 1] - p[i + 1]/2) + p[i + 3]/2) .put_symbol("RC"); } out.put_fix_number(p[np - 2] - p[np - 2]/2) .put_fix_number(p[np - 1] - p[np - 1]/2) .put_symbol("RL"); set_line_thickness_and_color(env); out.put_symbol("ST"); } break; case 'a': { if (np != 4) { error("4 arguments required for arc"); break; } set_line_thickness_and_color(env); double c[2]; if (adjust_arc_center(p, c)) out.put_fix_number(env->hpos + int(c[0])) .put_fix_number(env->vpos + int(c[1])) .put_fix_number(int(sqrt(c[0]*c[0] + c[1]*c[1]))) .put_float(degrees(atan2(-c[1], -c[0]))) .put_float(degrees(atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]))) .put_symbol("DA"); else out.put_fix_number(p[0] + p[2] + env->hpos) .put_fix_number(p[1] + p[3] + env->vpos) .put_fix_number(env->hpos) .put_fix_number(env->vpos) .put_symbol("DL"); } break; case 't': if (np == 0) line_thickness = -1; else { // troff gratuitously adds an extra 0 if (np != 1 && np != 2) { error("0 or 1 argument required for thickness"); break; } line_thickness = p[0]; } break; default: error("unrecognised drawing command `%1'", char(code)); break; } output_hpos = output_vpos = -1; }
void lj4_printer::draw(int code, int *p, int np, const environment *env) { switch (code) { case 'R': { if (np != 2) { error("2 arguments required for rule"); break; } int hpos = env->hpos; int vpos = env->vpos; int hsize = p[0]; int vsize = p[1]; if (hsize < 0) { hpos += hsize; hsize = -hsize; } if (vsize < 0) { vpos += vsize; vsize = -vsize; } if (!moveto(hpos, vpos)) return; printf("\033*c%da%db0P", hsize, vsize); break; } case 'l': if (np != 2) { error("2 arguments required for line"); break; } hpgl_init(); if (!moveto(env->hpos, env->vpos)) return; hpgl_start(); set_line_thickness(env->size, p[0] == 0 && p[1] == 0); printf("PD%d,%d", p[0], p[1]); hpgl_end(); break; case 'p': case 'P': { if (np & 1) { error("even number of arguments required for polygon"); break; } if (np == 0) { error("no arguments for polygon"); break; } hpgl_init(); if (!moveto(env->hpos, env->vpos)) return; hpgl_start(); if (code == 'p') set_line_thickness(env->size); printf("PMPD%d", p[0]); for (int i = 1; i < np; i++) printf(",%d", p[i]); printf("PM2%cP", code == 'p' ? 'E' : 'F'); hpgl_end(); break; } case '~': { if (np & 1) { error("even number of arguments required for spline"); break; } if (np == 0) { error("no arguments for spline"); break; } hpgl_init(); if (!moveto(env->hpos, env->vpos)) return; hpgl_start(); set_line_thickness(env->size); printf("PD%d,%d", p[0]/2, p[1]/2); const int tnum = 2; const int tden = 3; if (np > 2) { fputs("BR", stdout); for (int i = 0; i < np - 2; i += 2) { if (i != 0) putchar(','); printf("%d,%d,%d,%d,%d,%d", (p[i]*tnum)/(2*tden), (p[i + 1]*tnum)/(2*tden), p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden), p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden), (p[i] - p[i]/2) + p[i + 2]/2, (p[i + 1] - p[i + 1]/2) + p[i + 3]/2); } } printf("PR%d,%d", p[np - 2] - p[np - 2]/2, p[np - 1] - p[np - 1]/2); hpgl_end(); break; } case 'c': case 'C': // troff adds an extra argument to C if (np != 1 && !(code == 'C' && np == 2)) { error("1 argument required for circle"); break; } hpgl_init(); if (!moveto(env->hpos + p[0]/2, env->vpos)) return; hpgl_start(); if (code == 'c') { set_line_thickness(env->size); printf("CI%d", p[0]/2); } else printf("WG%d,0,360", p[0]/2); hpgl_end(); break; case 'e': case 'E': if (np != 2) { error("2 arguments required for ellipse"); break; } hpgl_init(); if (!moveto(env->hpos + p[0]/2, env->vpos)) return; hpgl_start(); printf("SC0,%.4f,0,-%.4f,2", hpgl_scale * double(p[0])/p[1], hpgl_scale); if (code == 'e') { set_line_thickness(env->size); printf("CI%d", p[1]/2); } else printf("WG%d,0,360", p[1]/2); printf("SC0,%.4f,0,-%.4f,2", hpgl_scale, hpgl_scale); hpgl_end(); break; case 'a': { if (np != 4) { error("4 arguments required for arc"); break; } hpgl_init(); if (!moveto(env->hpos, env->vpos)) return; hpgl_start(); set_line_thickness(env->size); double c[2]; if (adjust_arc_center(p, c)) { double sweep = ((atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]) - atan2(-c[1], -c[0])) * 180.0/PI); if (sweep > 0.0) sweep -= 360.0; printf("PDAR%d,%d,%f", int(c[0]), int(c[1]), sweep); } else printf("PD%d,%d", p[0] + p[2], p[1] + p[3]); hpgl_end(); } break; case 'f': if (np != 1 && np != 2) { error("1 argument required for fill"); break; } hpgl_init(); hpgl_start(); if (p[0] >= 0 && p[0] <= 1000) printf("FT10,%d", p[0]/10); hpgl_end(); break; case 'F': // not implemented yet break; case 't': { if (np == 0) { line_thickness = -1; } else { // troff gratuitously adds an extra 0 if (np != 1 && np != 2) { error("0 or 1 argument required for thickness"); break; } line_thickness = p[0]; } break; } default: error("unrecognised drawing command `%1'", char(code)); break; } }