Example #1
0
void ps_printer::fill_path(const environment *env)
{
  if (sbuf_color == *env->fill)
    out.put_symbol("FL");
  else
    set_color(env->fill, 1);
}
Example #2
0
void ps_printer::end_page(int)
{
  flush_sbuf();
  set_color(&default_color);
  out.put_symbol("EP");
  if (invis_count != 0) {
    error("missing `endinvis' command");
    invis_count = 0;
  }
}
Example #3
0
void ps_printer::set_color(color *col, int fill)
{
  sbuf_color = *col;
  unsigned int components[4];
  char s[3];
  color_scheme cs = col->get_components(components);
  s[0] = fill ? 'F' : 'C';
  s[2] = 0;
  switch (cs) {
  case DEFAULT:			// black
    out.put_symbol("0");
    s[1] = 'g';
    break;
  case RGB:
    out.put_color(Red)
       .put_color(Green)
       .put_color(Blue);
    s[1] = 'r';
    break;
  case CMY:
    col->get_cmyk(&Cyan, &Magenta, &Yellow, &Black);
    // fall through
  case CMYK:
    out.put_color(Cyan)
       .put_color(Magenta)
       .put_color(Yellow)
       .put_color(Black);
    s[1] = 'k';
    cmyk_flag = 1;
    break;
  case GRAY:
    out.put_color(Gray);
    s[1] = 'g';
    break;
  }
  out.put_symbol(s);
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
void ps_printer::do_import(char *arg, const environment *env)
{
  while (*arg == ' ' || *arg == '\n')
    arg++;
  char *p;
  for (p = arg; *p != '\0' && *p != ' ' && *p != '\n'; p++)
    ;
  if (*p != '\0')
    *p++ = '\0';
  int parms[6];
  int nparms = 0;
  while (nparms < 6) {
    char *end;
    long n = strtol(p, &end, 10);
    if (n == 0 && end == p)
      break;
    parms[nparms++] = int(n);
    p = end;
  }
  if (csalpha(*p) && (p[1] == '\0' || p[1] == ' ' || p[1] == '\n')) {
    error("scaling indicators not allowed in arguments for X import command");
    return;
  }
  while (*p == ' ' || *p == '\n')
    p++;
  if (nparms < 5) {
    if (*p == '\0')
      error("too few arguments for X import command");
    else
      error("invalid argument `%1' for X import command", p);
    return;
  }
  if (*p != '\0') {
    error("superfluous argument `%1' for X import command", p);
    return;
  }
  int llx = parms[0];
  int lly = parms[1];
  int urx = parms[2];
  int ury = parms[3];
  int desired_width = parms[4];
  int desired_height = parms[5];
  if (desired_width <= 0) {
    error("bad width argument `%1' for X import command: must be > 0",
	  desired_width);
    return;
  }
  if (nparms == 6 && desired_height <= 0) {
    error("bad height argument `%1' for X import command: must be > 0",
	  desired_height);
    return;
  }
  if (llx == urx) {
    error("llx and urx arguments for X import command must not be equal");
    return;
  }
  if (lly == ury) {
    error("lly and ury arguments for X import command must not be equal");
    return;
  }
  if (nparms == 5) {
    int old_wid = urx - llx;
    int old_ht = ury - lly;
    if (old_wid < 0)
      old_wid = -old_wid;
    if (old_ht < 0)
      old_ht = -old_ht;
    desired_height = int(desired_width*(double(old_ht)/double(old_wid)) + .5);
  }
  if (env->vpos - desired_height < 0)
    warning("top of imported graphic is above the top of the page");
  out.put_number(llx)
     .put_number(lly)
     .put_fix_number(desired_width)
     .put_number(urx - llx)
     .put_fix_number(-desired_height)
     .put_number(ury - lly)
     .put_fix_number(env->hpos)
     .put_fix_number(env->vpos)
     .put_symbol("PBEGIN");
  rm.import_file(arg, out);
  // do this here just in case application defines PEND
  out.put_symbol("end")
     .put_symbol("PEND");
}
Example #7
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;
}