⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 object.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 3 页
字号:
  arrow_at_end = at_end;  aht = a;}line_object::line_object(const position &s, const position &e,			 position *p, int i): v(p), n(i), linear_object(s, e){}void line_object::print(){  if (lt.type == line_type::invisible)    return;  out->line(strt, v, n, lt);  if (arrow_at_start)    draw_arrow(strt, strt-v[0], aht, lt);  if (arrow_at_end)    draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);}void line_object::update_bounding_box(bounding_box *p){  p->encompass(strt);  for (int i = 0; i < n; i++)    p->encompass(v[i]);}void line_object::move_by(const position &pos){  linear_object::move_by(pos);  for (int i = 0; i < n; i++)    v[i] += pos;}  void spline_object::update_bounding_box(bounding_box *p){  p->encompass(strt);  p->encompass(en);  /*  If  p1 = q1/2 + q2/2  p2 = q1/6 + q2*5/6  p3 = q2*5/6 + q3/6  p4 = q2/2 + q3/2  [ the points for the Bezier cubic ]  and  t = .5  then  (1-t)^3*p1 + 3*t*(t - 1)^2*p2 + 3*t^2*(1-t)*p3 + t^3*p4  [ the equation for the Bezier cubic ]  = .125*q1 + .75*q2 + .125*q3  */  for (int i = 1; i < n; i++)    p->encompass((i == 1 ? strt : v[i-2])*.125 + v[i-1]*.75 + v[i]*.125);}arrow_object::arrow_object(const position &s, const position &e,			   position *p, int i): line_object(s, e, p, i){}spline_object::spline_object(const position &s, const position &e,			     position *p, int i): line_object(s, e, p, i){}void spline_object::print(){  if (lt.type == line_type::invisible)    return;  out->spline(strt, v, n, lt);  if (arrow_at_start)    draw_arrow(strt, strt-v[0], aht, lt);  if (arrow_at_end)    draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);}line_object::~line_object(){  a_delete v;}linear_object *object_spec::make_line(position *curpos, direction *dirp){  static position last_line;  static int have_last_line = 0;  *dirp = dir;  // No need to look at at since `at' attribute sets `from' attribute.  position startpos = (flags & HAS_FROM) ? from : *curpos;  if (!(flags & HAS_SEGMENT)) {    if ((flags & IS_SAME) && (type == LINE_OBJECT || type == ARROW_OBJECT)	&& have_last_line)      segment_pos = last_line;    else       switch (dir) {      case UP_DIRECTION:	segment_pos.y = segment_height;	break;      case DOWN_DIRECTION:	segment_pos.y = -segment_height;	break;      case LEFT_DIRECTION:	segment_pos.x = -segment_width;	break;      case RIGHT_DIRECTION:	segment_pos.x = segment_width;	break;      default:	assert(0);      }  }  segment_list = new segment(segment_pos, segment_is_absolute, segment_list);  // reverse the segment_list so that it's in forward order  segment *old = segment_list;  segment_list = 0;  while (old != 0) {    segment *tem = old->next;    old->next = segment_list;    segment_list = old;    old = tem;  }  // Absolutise all movements  position endpos = startpos;  int nsegments = 0;  for (segment *s = segment_list; s; s = s->next, nsegments++)    if (s->is_absolute)      endpos = s->pos;    else {      endpos += s->pos;      s->pos = endpos;      s->is_absolute = 1;	// to avoid confusion    }  // handle chop  line_object *p = 0;  position *v = new position[nsegments];  int i = 0;  for (s = segment_list; s; s = s->next, i++)    v[i] = s->pos;  if (flags & IS_DEFAULT_CHOPPED) {    lookup_variable("circlerad", &start_chop);    end_chop = start_chop;    flags |= IS_CHOPPED;  }  if (flags & IS_CHOPPED) {    position start_chop_vec, end_chop_vec;    if (start_chop != 0.0) {      start_chop_vec = v[0] - startpos;      start_chop_vec *= start_chop / hypot(start_chop_vec);    }    if (end_chop != 0.0) {      end_chop_vec = (v[nsegments - 1]		      - (nsegments > 1 ? v[nsegments - 2] : startpos));      end_chop_vec *= end_chop / hypot(end_chop_vec);    }    startpos += start_chop_vec;    v[nsegments - 1] -= end_chop_vec;    endpos -= end_chop_vec;  }  switch (type) {  case SPLINE_OBJECT:    p = new spline_object(startpos, endpos, v, nsegments);    break;  case ARROW_OBJECT:    p = new arrow_object(startpos, endpos, v, nsegments);    break;  case LINE_OBJECT:    p = new line_object(startpos, endpos, v, nsegments);    break;  default:    assert(0);  }  have_last_line = 1;  last_line = endpos - startpos;  *curpos = endpos;  return p;}class arc_object : public linear_object {  int clockwise;  position cent;  double rad;public:  arc_object(int, const position &, const position &, const position &);  position origin() { return cent; }  position center() { return cent; }  double radius() { return rad; }  position north();  position south();  position east();  position west();  position north_east();  position north_west();  position south_east();  position south_west();  void update_bounding_box(bounding_box *);  object_type type() { return ARC_OBJECT; }  void print();  void move_by(const position &pos);};arc_object::arc_object(int cw, const position &s, const position &e,		       const position &c): linear_object(s, e), clockwise(cw), cent(c){  rad = hypot(c - s);}void arc_object::move_by(const position &pos){  linear_object::move_by(pos);  cent += pos;}// we get arc corners from the corresponding circleposition arc_object::north(){  position result(cent);  result.y += rad;  return result;}position arc_object::south(){  position result(cent);  result.y -= rad;  return result;}position arc_object::east(){  position result(cent);  result.x += rad;  return result;}position arc_object::west(){  position result(cent);  result.x -= rad;  return result;}position arc_object::north_east(){  position result(cent);  result.x += rad/M_SQRT2;  result.y += rad/M_SQRT2;  return result;}position arc_object::north_west(){  position result(cent);  result.x -= rad/M_SQRT2;  result.y += rad/M_SQRT2;  return result;}position arc_object::south_east(){  position result(cent);  result.x += rad/M_SQRT2;  result.y -= rad/M_SQRT2;  return result;}position arc_object::south_west(){  position result(cent);  result.x -= rad/M_SQRT2;  result.y -= rad/M_SQRT2;  return result;}void arc_object::print(){  if (lt.type == line_type::invisible)    return;  if (clockwise)    out->arc(en, cent, strt, lt);  else    out->arc(strt, cent, en, lt);  if (arrow_at_start) {    position c = cent - strt;    draw_arrow(strt,	       (clockwise ? position(c.y, -c.x) : position(-c.y, c.x)),	       aht, lt);  }  if (arrow_at_end) {    position e = en - cent;    draw_arrow(en,	       (clockwise ? position(e.y, -e.x) : position(-e.y, e.x)),	       aht, lt);  }}inline double max(double a, double b){  return a > b ? a : b;}void arc_object::update_bounding_box(bounding_box *p){  p->encompass(strt);  p->encompass(en);  position start_offset = strt - cent;  if (start_offset.x == 0.0 && start_offset.y == 0.0)    return;  position end_offset = en  - cent;  if (end_offset.x == 0.0 && end_offset.y == 0.0)    return;  double start_quad = atan2(start_offset.y, start_offset.x)/(M_PI/2.0);  double end_quad = atan2(end_offset.y, end_offset.x)/(M_PI/2.0);  if (clockwise) {    double temp = start_quad;    start_quad = end_quad;    end_quad = temp;  }  if (start_quad < 0.0)    start_quad += 4.0;  while (end_quad <= start_quad)    end_quad += 4.0;  double radius = max(hypot(start_offset), hypot(end_offset));  for (int q = int(start_quad) + 1; q < end_quad; q++) {    position offset;    switch (q % 4) {    case 0:      offset.x = radius;      break;    case 1:      offset.y = radius;      break;    case 2:      offset.x = -radius;      break;    case 3:      offset.y = -radius;      break;    }    p->encompass(cent + offset);  }}// We ignore the with attribute. The at attribute always refers to the center.linear_object *object_spec::make_arc(position *curpos, direction *dirp){  *dirp = dir;  int cw = (flags & IS_CLOCKWISE) != 0;  // compute the start  position startpos;  if (flags & HAS_FROM)    startpos = from;  else    startpos = *curpos;  if (!(flags & HAS_RADIUS))    lookup_variable("arcrad", &radius);  // compute the end  position endpos;  if (flags & HAS_TO)    endpos = to;  else {    position m(radius, radius);    // Adjust the signs.    if (cw) {      if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION)	m.x = -m.x;      if (dir == DOWN_DIRECTION || dir == RIGHT_DIRECTION)	m.y = -m.y;      *dirp = direction((dir + 3) % 4);    }    else {      if (dir == UP_DIRECTION || dir == LEFT_DIRECTION)	m.x = -m.x;      if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION)	m.y = -m.y;      *dirp = direction((dir + 1) % 4);    }    endpos = startpos + m;  }  // compute the center  position centerpos;  if (flags & HAS_AT)    centerpos = at;  else if (startpos == endpos)    centerpos = startpos;  else {    position h = (endpos - startpos)/2.0;    double d = hypot(h);    if (radius <= 0)      radius = .25;    // make the radius big enough    while (radius < d)      radius *= 2.0;    double alpha = acos(d/radius);    double theta = atan2(h.y, h.x);    if (cw)      theta -= alpha;    else      theta += alpha;    centerpos = position(cos(theta), sin(theta))*radius + startpos;  }  arc_object *p = new arc_object(cw, startpos, endpos, centerpos);  *curpos = endpos;  return p;}graphic_object *object_spec::make_linear(position *curpos, direction *dirp){  linear_object *obj;  if (type == ARC_OBJECT)    obj = make_arc(curpos, dirp);  else    obj = make_line(curpos, dirp);  if (type == ARROW_OBJECT      && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD)) == 0)    flags |= HAS_RIGHT_ARROW_HEAD;  if (obj && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD))) {    arrow_head_type a;    int at_start = (flags & HAS_LEFT_ARROW_HEAD) != 0;    int at_end = (flags & HAS_RIGHT_ARROW_HEAD) != 0;    if (flags & HAS_HEIGHT)      a.height = height;    else      lookup_variable("arrowht", &a.height);    if (flags & HAS_WIDTH)      a.width = width;    else      lookup_variable("arrowwid", &a.width);    double solid;    lookup_variable("arrowhead", &solid);    a.solid = solid != 0.0;    obj->add_arrows(at_start, at_end, a);  }  return obj;}object *object_spec::make_object(position *curpos, direction *dirp){  graphic_object *obj = 0;  switch (type) {  case BLOCK_OBJECT:    obj = make_block(curpos, dirp);    break;  case BOX_OBJECT:    obj = make_box(curpos, dirp);    break;  case TEXT_OBJECT:    obj = make_text(curpos, dirp);    break;  case ELLIPSE_OBJECT:    obj = make_ellipse(curpos, dirp);    break;  case CIRCLE_OBJECT:    obj = make_circle(curpos, dirp);    break;  case MOVE_OBJECT:    obj = make_move(curpos, dirp);    break;  case ARC_OBJECT:  case LINE_OBJECT:  case SPLINE_OBJECT:  case ARROW_OBJECT:    obj = make_linear(curpos, dirp);    break;  case MARK_OBJECT:  case OTHER_OBJECT:  default:    assert(0);    break;  }  if (obj) {    if (flags & IS_INVISIBLE)      obj->set_invisible();    if (text != 0)      obj->add_text(text, (flags & IS_ALIGNED) != 0);    if (flags & IS_DOTTED)      obj->set_dotted(dash_width);    else if (flags & IS_DASHED)      obj->set_dashed(dash_width);    double th;    if (flags & HAS_THICKNESS)      th = thickness;    else      lookup_variable("linethick", &th);    obj->set_thickness(th);    if (flags & (IS_DEFAULT_FILLED|IS_FILLED)) {      if (flags & IS_DEFAULT_FILLED)	lookup_variable("fillval", &fill);      if (fill < 0.0)	error("bad fill value %1", fill);      else	obj->set_fill(fill);    }  }  return obj;}struct string_list {  string_list *next;  char *str;  string_list(char *);  ~string_list();};string_list::string_list(char *s): next(0), str(s){}string_list::~string_list(){  a_delete str;}  /* A path is used to hold the argument to the with attribute. For example,`.nw' or `.A.s' or `.A'. The major operation on a path is to take a place and follow the path through the place to place within the place.Note that `.A.B.C.sw' will work. */path::path(corner c): label_list(0), crn(c){}path::path(char *l, corner c): crn(c){  label_list = new string_list(l);}path::~path(){  while (label_list) {    string_list *tem = label_list;    label_list = label_list->next;    delete tem;  }}void path::append(corner c){  assert(crn == 0);  crn = c;}void path::append(char *s){  for (string_list **p = &label_list; *p; p = &(*p)->next)    ;  *p = new string_list(s);}// return non-zero for successint path::follow(const place &pl, place *result) const{  const place *p = &pl;  for (string_list *lb = label_list; lb; lb = lb->next)    if (p->obj == 0 || (p = p->obj->find_label(lb->str)) == 0) {      lex_error("object does not contain a place `%1'", lb->str);      return 0;    }  if (crn == 0 || p->obj == 0)    *result = *p;  else {    position pos = ((p->obj)->*(crn))();    result->x = pos.x;    result->y = pos.y;    result->obj = 0;  }  return 1;}void print_object_list(object *p){  for (; p; p = p->next) {    p->print();    p->print_text();  }}void print_picture(object *obj){  bounding_box bb;  for (object *p = obj; p; p = p->next)    p->update_bounding_box(&bb);  double scale;  lookup_variable("scale", &scale);  out->start_picture(scale, bb.ll, bb.ur);  print_object_list(obj);  out->finish_picture();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -