From: Francois Fleuret Date: Sat, 27 Aug 2016 21:06:54 +0000 (+0200) Subject: Cairo support works, both to draw in the window and to write as a png image in a... X-Git-Url: https://fleuret.org/cgi-bin/gitweb/gitweb.cgi?a=commitdiff_plain;h=ea2a7fd04689794d3fb266e2b73bedb10953abb4;p=universe.git Cairo support works, both to draw in the window and to write as a png image in a file (or stream). --- diff --git a/main.cc b/main.cc index 905706d..e135189 100644 --- a/main.cc +++ b/main.cc @@ -25,8 +25,14 @@ using namespace std; #ifdef CAIRO_SUPPORT #include +static cairo_status_t write_cairo_to_file(void *closure, + const unsigned char *data, + unsigned int length) { + fwrite(data, 1, length, (FILE *) closure); + return CAIRO_STATUS_SUCCESS; +} -void generate_png(int width, int height, Universe *universe, const char *image_name) { +void generate_png(int width, int height, Universe *universe, FILE *file) { const int depth = 4; cairo_surface_t *image; cairo_t* context_resource; @@ -47,13 +53,11 @@ void generate_png(int width, int height, Universe *universe, const char *image_n universe->draw(context_resource); - cairo_surface_write_to_png(image, image_name); - - // fprintf(stdout, "Content-type: image/png\n\n"); - // cairo_surface_write_to_png_stream(image, write_cairo_to_file, stdout); + cairo_surface_write_to_png_stream(image, write_cairo_to_file, file); cairo_destroy(context_resource); cairo_surface_destroy(image); + delete[] data; } #endif @@ -205,6 +209,9 @@ int main(int argc, char **argv) { retina.set_location(manipulator.hand_x(), manipulator.hand_y()); SimpleWindow *window_main = 0, *window_brain = 0; +#ifdef CAIRO_SUPPORT + cairo_t *cairo_cr = 0; +#endif int window_main_fd = -1; @@ -238,6 +245,9 @@ int main(int argc, char **argv) { window_main = new SimpleWindow("Universe (main window)", 4, 4, task->width(), task->height()); window_main_fd = window_main->file_descriptor(); window_main->map(); +#ifdef CAIRO_SUPPORT + cairo_cr = window_main->get_cairo_context_resource(); +#endif cout << "When the main window has the focus, press `q' to quit and click and drag to move" << endl << "objects." << endl; window_brain = new SimpleWindow("Universe (brain)", @@ -325,11 +335,17 @@ int main(int argc, char **argv) { manipulator.hand_y()); if(window_main) { - // window_main->color(0.0, 0.0, 0.0); + window_main->color(0.0, 0.0, 0.0); window_main->color(1.0, 1.0, 1.0); window_main->fill(); task->draw(window_main); + +#ifdef CAIRO_SUPPORT + universe.draw(cairo_cr); +#else universe.draw(window_main); +#endif + manipulator.draw_on_universe(window_main); retina.draw_on_universe(window_main); @@ -434,15 +450,20 @@ int main(int argc, char **argv) { else if(strcmp(se.key, "s") == 0) { retina.save_as_ppm("/tmp/retina.ppm"); - cout << "Retina screen shot saved in /tmp/retina.ppm" << endl; + { XFigTracer tracer("/tmp/universe.fig"); universe.print_xfig(&tracer); } #ifdef CAIRO_SUPPORT - generate_png(task->width(), task->height(), &universe, "/tmp/universe.png"); + { + FILE *file = fopen("/tmp/universe.png", "w"); + generate_png(task->width(), task->height(), &universe, file); + // generate_png(task->width(), task->height(), &universe, "/tmp/universe.png"); + cout << "Universe image saved in /tmp/universe.png" << endl; + } #endif } diff --git a/polygon.cc b/polygon.cc index e957ec1..1c109c3 100644 --- a/polygon.cc +++ b/polygon.cc @@ -72,7 +72,8 @@ void Polygon::draw_contours(SimpleWindow *window) { x[n] = int(_x[n]); y[n] = int(_y[n]); } - window->color(0.0, 0.0, 0.0); + // window->color(0.0, 0.0, 0.0); + window->color(1.0, 1.0, 1.0); for(int n = 0; n < _nb_vertices; n++) { window->draw_line(x[n], y[n], x[(n+1)%_nb_vertices], y[(n+1)%_nb_vertices]); } @@ -80,15 +81,26 @@ void Polygon::draw_contours(SimpleWindow *window) { #ifdef CAIRO_SUPPORT void Polygon::draw(cairo_t* context_resource) { + cairo_set_line_width(context_resource, 1.0); + cairo_set_source_rgb (context_resource, _red, _green, _blue); + cairo_move_to(context_resource, _x[0], _y[0]); + for(int n = 0; n < _nb_vertices; n++) { + cairo_line_to(context_resource, _x[n], _y[n]); + } + cairo_close_path(context_resource); + cairo_stroke_preserve(context_resource); + cairo_fill(context_resource); } void Polygon::draw_contours(cairo_t* context_resource) { cairo_set_line_width(context_resource, 1.0); - cairo_set_source_rgb (context_resource, 0.0, 0.0, 0.0); + // cairo_set_source_rgb (context_resource, 0.0, 0.0, 0.0); + cairo_set_source_rgb (context_resource, 1.0, 1.0, 1.0); + cairo_move_to(context_resource, _x[0], _y[0]); for(int n = 0; n < _nb_vertices; n++) { - cairo_move_to(context_resource, _x[n], _y[n]); - cairo_line_to(context_resource, _x[(n+1)%_nb_vertices], _y[(n+1)%_nb_vertices]); + cairo_line_to(context_resource, _x[n], _y[n]); } + cairo_close_path(context_resource); cairo_stroke(context_resource); } #endif diff --git a/simple_window.cc b/simple_window.cc index 2864168..ae981ed 100644 --- a/simple_window.cc +++ b/simple_window.cc @@ -17,66 +17,67 @@ SimpleWindow::SimpleWindow(const char *name, int x, int y, int w, int h) { if (_display) { - Visual *v = XDefaultVisual(_display, DefaultScreen(_display)); + _screen = DefaultScreen(_display); + _visual = XDefaultVisual(_display, _screen); - _blue_mask = v->blue_mask; - _green_mask = v->green_mask; - _red_mask = v->red_mask; + _blue_mask = _visual->blue_mask; + _green_mask = _visual->green_mask; + _red_mask = _visual->red_mask; - if(_blue_mask == 0 || _green_mask == 0 || _red_mask == 0) { - cerr << "Can not deal with the colors on that display.\n"; - } + if(_blue_mask == 0 || _green_mask == 0 || _red_mask == 0) { + cerr << "Can not deal with the colors on that display.\n"; + } - _red_shift = 1; - while(!(_red_mask & 1)) { - _red_mask = _red_mask >> 1; - _red_shift = _red_shift << 1; - } + _red_shift = 1; + while(!(_red_mask & 1)) { + _red_mask = _red_mask >> 1; + _red_shift = _red_shift << 1; + } - _green_shift = 1; - while(!(_green_mask & 1)) { - _green_mask = _green_mask >> 1; - _green_shift = _green_shift << 1; - } + _green_shift = 1; + while(!(_green_mask & 1)) { + _green_mask = _green_mask >> 1; + _green_shift = _green_shift << 1; + } - _blue_shift = 1; - while(!(_blue_mask & 1)) { - _blue_mask = _blue_mask >> 1; - _blue_shift = _blue_shift << 1; - } + _blue_shift = 1; + while(!(_blue_mask & 1)) { + _blue_mask = _blue_mask >> 1; + _blue_shift = _blue_shift << 1; + } - _gc = DefaultGC(_display, DefaultScreen(_display)); + _gc = DefaultGC(_display, DefaultScreen(_display)); - XSetWindowAttributes xswa; + XSetWindowAttributes xswa; - _pixmap = XCreatePixmap(_display, DefaultRootWindow(_display), - _width, _height, DisplayPlanes(_display, DefaultScreen(_display))); + _pixmap = XCreatePixmap(_display, DefaultRootWindow(_display), + _width, _height, DisplayPlanes(_display, DefaultScreen(_display))); - xswa.background_pixmap = _pixmap; - xswa.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | KeyReleaseMask; - xswa.backing_store = Always; + xswa.background_pixmap = _pixmap; + xswa.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | KeyReleaseMask; + xswa.backing_store = Always; - _window = XCreateWindow(_display, DefaultRootWindow(_display), x, y, _width, _height, - 0, 0, InputOutput, CopyFromParent, - CWBackPixmap | CWEventMask | CWBackingStore, - &xswa); + _window = XCreateWindow(_display, DefaultRootWindow(_display), x, y, _width, _height, + 0, 0, InputOutput, CopyFromParent, + CWBackPixmap | CWEventMask | CWBackingStore, + &xswa); - XSizeHints size_hints; - size_hints.flags = PMinSize | PMaxSize | USPosition; - size_hints.x = x; // These two lines do not seem to be required - size_hints.y = y; // ... - size_hints.min_width = _width; - size_hints.min_height = _height; - size_hints.max_width = _width; - size_hints.max_height = _height; - XSetNormalHints(_display, _window, &size_hints); + XSizeHints size_hints; + size_hints.flags = PMinSize | PMaxSize | USPosition; + size_hints.x = x; // These two lines do not seem to be required + size_hints.y = y; // ... + size_hints.min_width = _width; + size_hints.min_height = _height; + size_hints.max_width = _width; + size_hints.max_height = _height; + XSetNormalHints(_display, _window, &size_hints); - XStoreName(_display, _window, name); + XStoreName(_display, _window, name); - XSetState(_display, _gc, 0, 0, GXcopy, AllPlanes); - XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height); - XFlush(_display); - } else abort(); + XSetState(_display, _gc, 0, 0, GXcopy, AllPlanes); + XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height); + XFlush(_display); + } else abort(); } @@ -210,3 +211,15 @@ SimpleEvent SimpleWindow::event() { } else se.type = SimpleEvent::NO_EVENT; return se; } + +#ifdef CAIRO_SUPPORT +cairo_t *SimpleWindow::get_cairo_context_resource() { + cairo_surface_t *surface; + + surface = cairo_xlib_surface_create(_display, _pixmap, _visual, _width, _height); + + cairo_xlib_surface_set_size(surface, _width, _height); + + return cairo_create(surface); +} +#endif diff --git a/simple_window.h b/simple_window.h index 81c3116..6339609 100644 --- a/simple_window.h +++ b/simple_window.h @@ -14,6 +14,11 @@ using namespace std; #include #include +#ifdef CAIRO_SUPPORT +#include +#include +#endif + class SimpleEvent { public: @@ -32,6 +37,8 @@ public: class SimpleWindow { Display *_display; + int _screen; + Visual *_visual; Window _window; Pixmap _pixmap; GC _gc; @@ -62,6 +69,10 @@ public: virtual int file_descriptor(); virtual SimpleEvent event(); + +#ifdef CAIRO_SUPPORT + virtual cairo_t *get_cairo_context_resource(); +#endif }; #endif