Cairo support works, both to draw in the window and to write as a png image in a...
authorFrancois Fleuret <francois@fleuret.org>
Sat, 27 Aug 2016 21:06:54 +0000 (23:06 +0200)
committerFrancois Fleuret <francois@fleuret.org>
Sat, 27 Aug 2016 21:06:54 +0000 (23:06 +0200)
main.cc
polygon.cc
simple_window.cc
simple_window.h

diff --git a/main.cc b/main.cc
index 905706d..e135189 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -25,8 +25,14 @@ using namespace std;
 #ifdef CAIRO_SUPPORT
 #include <cairo.h>
 
+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
 
               }
index e957ec1..1c109c3 100644 (file)
@@ -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
index 2864168..ae981ed 100644 (file)
@@ -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
index 81c3116..6339609 100644 (file)
@@ -14,6 +14,11 @@ using namespace std;
 #include <X11/Xutil.h>
 #include <X11/XKBlib.h>
 
+#ifdef CAIRO_SUPPORT
+#include <cairo.h>
+#include <cairo-xlib.h>
+#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