📄 object.cc
字号:
for (p = t, len = 0; p; p = p->next, len++) { text[len].text = p->text; p->text = 0; text[len].adj = p->adj; text[len].filename = p->filename; text[len].lineno = p->lineno; } } ntext = len;}void graphic_object::print_text(){ double angle = 0.0; if (aligned) { position d(end() - start()); if (d.x != 0.0 || d.y != 0.0) angle = atan2(d.y, d.x); } if (text != 0) out->text(center(), text, ntext, angle);}graphic_object::~graphic_object(){ if (text) ad_delete(ntext) text;}class rectangle_object : public graphic_object {protected: position cent; position dim;public: rectangle_object(const position &); double width() { return dim.x; } double height() { return dim.y; } position origin() { return cent; } position center() { return cent; } position north() { return position(cent.x, cent.y + dim.y/2.0); } position south() { return position(cent.x, cent.y - dim.y/2.0); } position east() { return position(cent.x + dim.x/2.0, cent.y); } position west() { return position(cent.x - dim.x/2.0, cent.y); } position north_east() { return position(cent.x + dim.x/2.0, cent.y + dim.y/2.0); } position north_west() { return position(cent.x - dim.x/2.0, cent.y + dim.y/2.0); } position south_east() { return position(cent.x + dim.x/2.0, cent.y - dim.y/2.0); } position south_west() { return position(cent.x - dim.x/2.0, cent.y - dim.y/2.0); } object_type type() = 0; void update_bounding_box(bounding_box *); void move_by(const position &);};rectangle_object::rectangle_object(const position &d): dim(d){}void rectangle_object::update_bounding_box(bounding_box *p){ p->encompass(cent - dim/2.0); p->encompass(cent + dim/2.0);}void rectangle_object::move_by(const position &a){ cent += a;}class closed_object : public rectangle_object {public: closed_object(const position &); object_type type() = 0; void set_fill(double);protected: double fill; // < 0 if not filled};closed_object::closed_object(const position &pos): rectangle_object(pos), fill(-1.0){}void closed_object::set_fill(double f){ assert(f >= 0.0); fill = f;}class box_object : public closed_object { double xrad; double yrad;public: box_object(const position &, double); object_type type() { return BOX_OBJECT; } void print(); position north_east(); position north_west(); position south_east(); position south_west();};box_object::box_object(const position &pos, double r): closed_object(pos), xrad(dim.x > 0 ? r : -r), yrad(dim.y > 0 ? r : -r){}const double CHOP_FACTOR = 1.0 - 1.0/M_SQRT2;position box_object::north_east(){ return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad, cent.y + dim.y/2.0 - CHOP_FACTOR*yrad);}position box_object::north_west(){ return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad, cent.y + dim.y/2.0 - CHOP_FACTOR*yrad);}position box_object::south_east(){ return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad, cent.y - dim.y/2.0 + CHOP_FACTOR*yrad);}position box_object::south_west(){ return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad, cent.y - dim.y/2.0 + CHOP_FACTOR*yrad);}void box_object::print(){ if (lt.type == line_type::invisible && fill < 0.0) return; if (xrad == 0.0) { distance dim2 = dim/2.0; position vec[4]; vec[0] = cent + position(dim2.x, -dim2.y); vec[1] = cent + position(dim2.x, dim2.y); vec[2] = cent + position(-dim2.x, dim2.y); vec[3] = cent + position(-dim2.x, -dim2.y); out->polygon(vec, 4, lt, fill); } else { distance abs_dim(fabs(dim.x), fabs(dim.y)); out->rounded_box(cent, abs_dim, fabs(xrad), lt, fill); }}graphic_object *object_spec::make_box(position *curpos, direction *dirp){ static double last_box_height; static double last_box_width; static double last_box_radius; static int have_last_box = 0; if (!(flags & HAS_HEIGHT)) { if ((flags & IS_SAME) && have_last_box) height = last_box_height; else lookup_variable("boxht", &height); } if (!(flags & HAS_WIDTH)) { if ((flags & IS_SAME) && have_last_box) width = last_box_width; else lookup_variable("boxwid", &width); } if (!(flags & HAS_RADIUS)) { if ((flags & IS_SAME) && have_last_box) radius = last_box_radius; else lookup_variable("boxrad", &radius); } last_box_width = width; last_box_height = height; last_box_radius = radius; have_last_box = 1; radius = fabs(radius); if (radius*2.0 > fabs(width)) radius = fabs(width/2.0); if (radius*2.0 > fabs(height)) radius = fabs(height/2.0); box_object *p = new box_object(position(width, height), radius); if (!position_rectangle(p, curpos, dirp)) { delete p; p = 0; } return p;}// return non-zero for successint object_spec::position_rectangle(rectangle_object *p, position *curpos, direction *dirp){ position pos; dir = *dirp; // ignore any direction in attribute list position motion; switch (dir) { case UP_DIRECTION: motion.y = p->height()/2.0; break; case DOWN_DIRECTION: motion.y = -p->height()/2.0; break; case LEFT_DIRECTION: motion.x = -p->width()/2.0; break; case RIGHT_DIRECTION: motion.x = p->width()/2.0; break; default: assert(0); } if (flags & HAS_AT) { pos = at; if (flags & HAS_WITH) { place offset; place here; here.obj = p; if (!with->follow(here, &offset)) return 0; pos -= offset; } } else { pos = *curpos; pos += motion; } p->move_by(pos); pos += motion; *curpos = pos; return 1;}class block_object : public rectangle_object { object_list oblist; PTABLE(place) *tbl;public: block_object(const position &, const object_list &ol, PTABLE(place) *t); ~block_object(); place *find_label(const char *); object_type type(); void move_by(const position &); void print();};block_object::block_object(const position &d, const object_list &ol, PTABLE(place) *t): oblist(ol), tbl(t), rectangle_object(d){}block_object::~block_object(){ delete tbl; object *p = oblist.head; while (p != 0) { object *tem = p; p = p->next; delete tem; }}void block_object::print(){ out->begin_block(south_west(), north_east()); print_object_list(oblist.head); out->end_block();}static void adjust_objectless_places(PTABLE(place) *tbl, const position &a){ // Adjust all the labels that aren't attached to objects. PTABLE_ITERATOR(place) iter(tbl); const char *key; place *pl; while (iter.next(&key, &pl)) if (key && csupper(key[0]) && pl->obj == 0) { pl->x += a.x; pl->y += a.y; }}void block_object::move_by(const position &a){ cent += a; for (object *p = oblist.head; p; p = p->next) p->move_by(a); adjust_objectless_places(tbl, a);}place *block_object::find_label(const char *name){ return tbl->lookup(name);}object_type block_object::type(){ return BLOCK_OBJECT;}graphic_object *object_spec::make_block(position *curpos, direction *dirp){ bounding_box bb; for (object *p = oblist.head; p; p = p->next) p->update_bounding_box(&bb); position dim; if (!bb.blank) { position m = -(bb.ll + bb.ur)/2.0; for (object *p = oblist.head; p; p = p->next) p->move_by(m); adjust_objectless_places(tbl, m); dim = bb.ur - bb.ll; } if (flags & HAS_WIDTH) dim.x = width; if (flags & HAS_HEIGHT) dim.y = height; block_object *block = new block_object(dim, oblist, tbl); if (!position_rectangle(block, curpos, dirp)) { delete block; block = 0; } tbl = 0; oblist.head = oblist.tail = 0; return block;}class text_object : public rectangle_object {public: text_object(const position &); object_type type() { return TEXT_OBJECT; }};text_object::text_object(const position &d): rectangle_object(d){}graphic_object *object_spec::make_text(position *curpos, direction *dirp){ if (!(flags & HAS_HEIGHT)) { lookup_variable("textht", &height); int nitems = 0; for (text_item *t = text; t; t = t->next) nitems++; height *= nitems; } if (!(flags & HAS_WIDTH)) lookup_variable("textwid", &width); text_object *p = new text_object(position(width, height)); if (!position_rectangle(p, curpos, dirp)) { delete p; p = 0; } return p;}class ellipse_object : public closed_object {public: ellipse_object(const position &); position north_east() { return position(cent.x + dim.x/(M_SQRT2*2.0), cent.y + dim.y/(M_SQRT2*2.0)); } position north_west() { return position(cent.x - dim.x/(M_SQRT2*2.0), cent.y + dim.y/(M_SQRT2*2.0)); } position south_east() { return position(cent.x + dim.x/(M_SQRT2*2.0), cent.y - dim.y/(M_SQRT2*2.0)); } position south_west() { return position(cent.x - dim.x/(M_SQRT2*2.0), cent.y - dim.y/(M_SQRT2*2.0)); } double radius() { return dim.x/2.0; } object_type type() { return ELLIPSE_OBJECT; } void print();};ellipse_object::ellipse_object(const position &d): closed_object(d){}void ellipse_object::print(){ if (lt.type == line_type::invisible && fill < 0.0) return; out->ellipse(cent, dim, lt, fill);}graphic_object *object_spec::make_ellipse(position *curpos, direction *dirp){ static double last_ellipse_height; static double last_ellipse_width; static int have_last_ellipse = 0; if (!(flags & HAS_HEIGHT)) { if ((flags & IS_SAME) && have_last_ellipse) height = last_ellipse_height; else lookup_variable("ellipseht", &height); } if (!(flags & HAS_WIDTH)) { if ((flags & IS_SAME) && have_last_ellipse) width = last_ellipse_width; else lookup_variable("ellipsewid", &width); } last_ellipse_width = width; last_ellipse_height = height; have_last_ellipse = 1; ellipse_object *p = new ellipse_object(position(width, height)); if (!position_rectangle(p, curpos, dirp)) { delete p; return 0; } return p;}class circle_object : public ellipse_object {public: circle_object(double); object_type type() { return CIRCLE_OBJECT; } void print();};/* * XXX call posref to gain reference to avoid g++ core dump. * From: Chris Torek <torek@BSDI.COM> */circle_object::circle_object(double diam): ellipse_object(posref(position(diam, diam))){}void circle_object::print(){ if (lt.type == line_type::invisible && fill < 0.0) return; out->circle(cent, dim.x/2.0, lt, fill);}graphic_object *object_spec::make_circle(position *curpos, direction *dirp){ static double last_circle_radius; static int have_last_circle = 0; if (!(flags & HAS_RADIUS)) { if ((flags & IS_SAME) && have_last_circle) radius = last_circle_radius; else lookup_variable("circlerad", &radius); } last_circle_radius = radius; have_last_circle = 1; circle_object *p = new circle_object(radius*2.0); if (!position_rectangle(p, curpos, dirp)) { delete p; return 0; } return p;}class move_object : public graphic_object { position strt; position en;public: move_object(const position &s, const position &e); position origin() { return en; } object_type type() { return MOVE_OBJECT; } void update_bounding_box(bounding_box *); void move_by(const position &);};move_object::move_object(const position &s, const position &e): strt(s), en(e){}void move_object::update_bounding_box(bounding_box *p){ p->encompass(strt); p->encompass(en);}void move_object::move_by(const position &a){ strt += a; en += a;}graphic_object *object_spec::make_move(position *curpos, direction *dirp){ static position last_move; static int have_last_move = 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) && have_last_move) segment_pos = last_move; 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; } // Compute the end position. position endpos = startpos; for (segment *s = segment_list; s; s = s->next) if (s->is_absolute) endpos = s->pos; else endpos += s->pos; have_last_move = 1; last_move = endpos - startpos; move_object *p = new move_object(startpos, endpos); *curpos = endpos; return p;}class linear_object : public graphic_object {protected: char arrow_at_start; char arrow_at_end; arrow_head_type aht; position strt; position en;public: linear_object(const position &s, const position &e); position start() { return strt; } position end() { return en; } void move_by(const position &); void update_bounding_box(bounding_box *) = 0; object_type type() = 0; void add_arrows(int at_start, int at_end, const arrow_head_type &);};class line_object : public linear_object {protected: position *v; int n;public: line_object(const position &s, const position &e, position *, int); ~line_object(); position origin() { return strt; } position center() { return (strt + en)/2.0; } position north() { return (en.y - strt.y) > 0 ? en : strt; } position south() { return (en.y - strt.y) < 0 ? en : strt; } position east() { return (en.x - strt.x) > 0 ? en : strt; } position west() { return (en.x - strt.x) < 0 ? en : strt; } object_type type() { return LINE_OBJECT; } void update_bounding_box(bounding_box *); void print(); void move_by(const position &);};class arrow_object : public line_object {public: arrow_object(const position &, const position &, position *, int); object_type type() { return ARROW_OBJECT; }};class spline_object : public line_object {public: spline_object(const position &, const position &, position *, int); object_type type() { return SPLINE_OBJECT; } void print(); void update_bounding_box(bounding_box *);};linear_object::linear_object(const position &s, const position &e): strt(s), en(e), arrow_at_start(0), arrow_at_end(0){}void linear_object::move_by(const position &a){ strt += a; en += a;}void linear_object::add_arrows(int at_start, int at_end, const arrow_head_type &a){ arrow_at_start = at_start;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -