void ps_printer::set_style(const style &sty) { char buf[1 + INT_DIGITS + 1]; for (int i = 0; i < ndefined_styles; i++) if (sty == defined_styles[i]) { sprintf(buf, "F%d", i); out.put_symbol(buf); return; } if (ndefined_styles >= MAX_DEFINED_STYLES) ndefined_styles = 0; sprintf(buf, "F%d", ndefined_styles); out.put_literal_symbol(buf); const char *psname = sty.f->get_internal_name(); if (psname == 0) fatal("no internalname specified for font `%1'", sty.f->get_name()); char *encoding = ((ps_font *)sty.f)->encoding; if (sty.sub == 0) { if (encoding != 0) { char *s = ((ps_font *)sty.f)->reencoded_name; if (s == 0) { int ei = set_encoding_index((ps_font *)sty.f); char *tem = new char[strlen(psname) + 1 + INT_DIGITS + 1]; sprintf(tem, "%s@%d", psname, ei); psname = tem; ((ps_font *)sty.f)->reencoded_name = tem; } else psname = s; } } else psname = get_subfont(sty.sub, psname); out.put_fix_number((font::res/(72*font::sizescale))*sty.point_size); if (sty.height != 0 || sty.slant != 0) { int h = sty.height == 0 ? sty.point_size : sty.height; h *= font::res/(72*font::sizescale); int c = int(h*tan(radians(sty.slant)) + .5); out.put_fix_number(c) .put_fix_number(h) .put_literal_symbol(psname) .put_symbol("MF"); } else { out.put_literal_symbol(psname) .put_symbol("SF"); } defined_styles[ndefined_styles++] = sty; }
void ps_printer::do_file(char *arg, const environment *env) { while (csspace(*arg)) arg++; if (*arg == '\0') { error("missing argument to X file command"); return; } const char *filename = arg; do { ++arg; } while (*arg != '\0' && *arg != ' ' && *arg != '\n'); out.put_fix_number(env->hpos) .put_fix_number(env->vpos) .put_symbol("EBEGIN"); rm.import_file(filename, out); out.put_symbol("EEND"); output_hpos = output_vpos = -1; output_style.f = 0; output_draw_point_size = -1; output_line_thickness = -1; ndefined_styles = 0; if (!ndefs) ndefs = 1; }
void ps_printer::do_exec(char *arg, const environment *env) { flush_sbuf(); while (csspace(*arg)) arg++; if (*arg == '\0') { error("missing argument to X exec command"); return; } if (!check_line_lengths(arg)) { error("lines in X exec command must not be more than 255 characters long"); return; } out.put_fix_number(env->hpos) .put_fix_number(env->vpos) .put_symbol("EBEGIN") .special(arg) .put_symbol("EEND"); output_hpos = output_vpos = -1; output_style.f = 0; output_draw_point_size = -1; output_line_thickness = -1; ndefined_styles = 0; if (!ndefs) ndefs = 1; }
void ps_printer::set_line_thickness_and_color(const environment *env) { if (line_thickness < 0) { if (output_draw_point_size != env->size) { // we ought to check for overflow here int lw = ((font::res/(72*font::sizescale))*linewidth*env->size)/1000; out.put_fix_number(lw) .put_symbol("LW"); output_draw_point_size = env->size; output_line_thickness = -1; } } else { if (output_line_thickness != line_thickness) { out.put_fix_number(line_thickness) .put_symbol("LW"); output_line_thickness = line_thickness; output_draw_point_size = -1; } } if (sbuf_color != *env->col) set_color(env->col); }
void ps_printer::flush_sbuf() { enum { NONE, RELATIVE_H, RELATIVE_V, RELATIVE_HV, ABSOLUTE } motion = NONE; int space_flag = 0; if (sbuf_len == 0) return; if (output_style != sbuf_style) { set_style(sbuf_style); output_style = sbuf_style; } int extra_space = 0; if (output_hpos < 0 || output_vpos < 0) motion = ABSOLUTE; else { if (output_hpos != sbuf_start_hpos) motion = RELATIVE_H; if (output_vpos != sbuf_vpos) { if (motion != NONE) motion = RELATIVE_HV; else motion = RELATIVE_V; } } if (sbuf_space_code >= 0) { int w = sbuf_style.f->get_width(space_glyph, sbuf_style.point_size); if (w + sbuf_kern != sbuf_space_width) { if (sbuf_space_code != output_space_code) { set_space_code(sbuf_space_code); output_space_code = sbuf_space_code; } space_flag = 1; extra_space = sbuf_space_width - w - sbuf_kern; if (sbuf_space_diff_count > sbuf_space_count/2) extra_space++; else if (sbuf_space_diff_count < -(sbuf_space_count/2)) extra_space--; } } if (space_flag) out.put_fix_number(extra_space); if (sbuf_kern != 0) out.put_fix_number(sbuf_kern); out.put_string(sbuf, sbuf_len); char command_array[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'}; char sym[2]; sym[0] = command_array[motion*4 + space_flag + 2*(sbuf_kern != 0)]; sym[1] = '\0'; switch (motion) { case NONE: break; case ABSOLUTE: out.put_fix_number(sbuf_start_hpos) .put_fix_number(sbuf_vpos); break; case RELATIVE_H: out.put_fix_number(sbuf_start_hpos - output_hpos); break; case RELATIVE_V: out.put_fix_number(sbuf_vpos - output_vpos); break; case RELATIVE_HV: out.put_fix_number(sbuf_start_hpos - output_hpos) .put_fix_number(sbuf_vpos - output_vpos); break; default: assert(0); } out.put_symbol(sym); output_hpos = sbuf_end_hpos; output_vpos = sbuf_vpos; sbuf_len = 0; }
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; }