#ifdef HAVE_CONFIG_H # include #endif #include "view.hh" #include "grafix.hh" #include #include View::View(Grafix *grafix) : _grafix(grafix), _display(grafix->display()), _window(None), _buffer(0), _drawable(None), _cleared(0), _trails(false) { } View::View(Grafix *grafix, Window window) : _grafix(grafix), _display(grafix->display()), _window(window), _buffer(0), _drawable(window), _cleared(0), _x_scale(1), _y_scale(1), _trails(false) { XWindowAttributes attr; XGetWindowAttributes(_display, _window, &attr); _window_width = attr.width; _window_height = attr.height; reset(); XSetWindowBackground(_display, _window, BlackPixelOfScreen(attr.screen)); #ifdef HAVE_X11_DOUBLE_BUFFERING int minor, major; if (XdbeQueryExtension(_display, &major, &minor)) { _db_swap_info.swap_action = XdbeBackground; _buffer = XdbeAllocateBackBufferName(_display, _window, XdbeBackground); _db_swap_info.swap_window = _window; } #endif } View::~View() { } void View::set_double_buffer(bool on) { if (on && _buffer) _drawable = _buffer; else _drawable = _window; } void View::set_window_size(int width, int height) { _offset.y -= (height - _window_height) / _y_scale; _window_width = width; _window_height = height; } Point View::upper_right() const { return _offset + Point(_window_width / _x_scale, _window_height / _y_scale); } void View::reset() { _x_scale = _y_scale = 1; _offset = Point(-_window_width / 2, -_window_height / 2); } void View::zoom(double factor) { Point c = _offset + Point(_window_width / _x_scale / 2, _window_height / _y_scale / 2); _x_scale *= factor; _y_scale *= factor; _offset = c - Point(_window_width / _x_scale / 2, _window_height / _y_scale / 2); } void View::screen_shift(double x, double y) { _offset.x += _window_width * x / _x_scale; _offset.y += _window_height * y / _y_scale; } inline GC View::xgc(int gc) const { return _grafix->xgc(gc); } void View::clear() { if (_drawable == _window) XClearWindow(_display, _window); else if (_cleared) _cleared = false; else XFillRectangle(_display, _drawable, xgc(0), 0, 0, _window_width, _window_height); } void View::expose() { #ifdef HAVE_X11_DOUBLE_BUFFERING if (_drawable == _buffer) { XdbeSwapBuffers(_display, &_db_swap_info, 1); _cleared = true; } #endif } void View::draw_line(int gc, const Point &p1, const Point &p2) { XPoint ip1 = x_transform(p1); XPoint ip2 = x_transform(p2); XDrawLine(_display, _drawable, xgc(gc), ip1.x, ip1.y, ip2.x, ip2.y); } void View::draw_lines(int gc, int np, const Point *p, bool closed) { XPoint buf[32]; XPoint *xp = (np > 31 ? new XPoint[np+1] : buf); for (int i = 0; i < np; i++) xp[i] = x_transform(p[i]); if (closed) { xp[np] = xp[0]; np++; } XDrawLines(_display, _drawable, xgc(gc), xp, np, CoordModeOrigin); if (xp != buf) delete[] xp; } void View::draw_arc(int gc, const Point &p, double r, double angle1, double angle2) { XPoint ll = x_transform(p + Point(-r, -r)); XPoint ur = x_transform(p + Point(r, r)); angle2 -= angle1; XDrawArc(_display, _drawable, xgc(gc), ll.x, ur.y, ur.x-ll.x, ll.y-ur.y, (int)(angle1 / M_PI * 11520), (int)(angle2 / M_PI * 11520)); } void View::fill_poly(int gc, int np, const Point *p) { XPoint buf[32]; XPoint *xp = (np > 32 ? new XPoint[np] : buf); for (int i = 0; i < np; i++) xp[i] = x_transform(p[i]); XFillPolygon(_display, _drawable, xgc(gc), xp, np, Nonconvex, CoordModeOrigin); if (xp != buf) delete[] xp; } void View::fill_arc(int gc, const Point &p, double r, double angle1, double angle2) { XPoint ll = x_transform(p + Point(-r, -r)); XPoint ur = x_transform(p + Point(r, r)); angle2 -= angle1; XFillArc(_display, _drawable, xgc(gc), ll.x, ur.y, ur.x-ll.x, ll.y-ur.y, (int)(angle1 / M_PI * 11520), (int)(angle2 / M_PI * 11520)); } EPSView::EPSView(View *v, FILE *f) : View(v->grafix()), _f(f) { _window_width = v->window_width(); _window_height = v->window_height(); _offset = v->offset(); _x_scale = v->x_scale(); _y_scale = v->y_scale(); } void EPSView::draw_line(int, const Point &p1, const Point &p2) { Point ip1 = transform(p1); Point ip2 = transform(p2); fprintf(_f, "%g %g moveto %g %g lineto stroke\n", ip1.x, ip1.y, ip2.x, ip2.y); } void EPSView::draw_lines(int, int np, const Point *p, bool closed) { Point p0 = transform(p[0]); fprintf(_f, "%g %g moveto ", p0.x, p0.y); for (int i = 1; i < np; i++) { Point pi = transform(p[i]); fprintf(_f, "%g %g lineto ", pi.x, pi.y); } if (closed) fprintf(_f, "closepath "); fprintf(_f, "stroke\n"); } void EPSView::draw_arc(int, const Point &p, double r, double angle1, double angle2) { Point ip = transform(p); fprintf(_f, "newpath %g %g %g %g %g arc stroke\n", ip.x, ip.y, r * _x_scale, angle1 * 180 / M_PI, angle2 * 180 / M_PI); } void EPSView::fill_poly(int gc, int np, const Point *p) { if (gc) draw_lines(gc, np, p, true); else { return; Point p0 = transform(p[0]); fprintf(_f, "%g %g moveto ", p0.x, p0.y); for (int i = 1; i < np; i++) { Point pi = transform(p[i]); fprintf(_f, "%g %g lineto ", pi.x, pi.y); } fprintf(_f, "closepath currentrgbcolor 1 setgray fill setrgbcolor\n"); } } void EPSView::fill_arc(int gc, const Point &p, double r, double angle1, double angle2) { draw_arc(gc, p, r, angle1, angle2); }