note the sample builds snapshot{} out of _snapshot{}, providing the temp file that cairo (apparently!) requires. the user can pass the permanent filename they want to use into snapshot{}

advise if I got the patch format wrong or anything!
diff --git a/shoes/canvas.c b/shoes/canvas.c
index c47d1b8..fd39447 100644
--- a/shoes/canvas.c
+++ b/shoes/canvas.c
@@ -2264,3 +2264,76 @@ shoes_canvas_dialog_plain(VALUE self)
   return shoes_color_new(GetRValue(winc), GetGValue(winc), GetBValue(winc), SHOES_COLOR_OPAQUE);
 #endif
 }
+
+typedef cairo_public cairo_surface_t * (cairo_surface_function_t) (const char *filename, double width, double height);
+
+static  cairo_public cairo_surface_t * 
+nada (const char *filename, double width, double height)
+{ 
+  return NULL; 
+}
+
+#include "cairo-svg.h"
+#include "cairo-ps.h"
+#include "cairo-pdf.h"
+
+//  TODO  can ya turn on -Wall in the compiler?
+
+static cairo_surface_function_t *
+get_snapshot_surface(VALUE _format)
+{
+  ID format = SYM2ID (_format);
+  if (format == rb_intern ("pdf"))  return & cairo_pdf_surface_create;
+  if (format == rb_intern ("ps"))   return & cairo_ps_surface_create;
+  if (format == rb_intern ("svg"))  return & cairo_svg_surface_create;
+  return nada;
+}
+
+VALUE
+shoes_canvas_snapshot(int argc, VALUE *argv, VALUE self)
+{
+  SETUP();
+  ID   s_filename = rb_intern ("filename");
+  ID   s_format   = rb_intern ("format");
+  VALUE  block    = Qnil;
+  VALUE _filename = Qnil;
+  VALUE _format   = Qnil;
+  VALUE  hash     = Qnil;
+  argc = rb_scan_args (argc, argv, "1&", &hash, &block);
+
+  if (argc == 1 && rb_obj_is_kind_of(hash, rb_cHash))
+  {
+    _filename = ATTR(hash, filename);
+    _format   = ATTR(hash, format);
+  }
+  if (NIL_P(block) || NIL_P(_filename) || NIL_P(_format))
+  {
+    rb_raise(rb_eArgError, "wrong arguments for _snapshot({:filename=>'...',"
+                              ":format=>:pdf|:ps|:svg}, &block)\n");
+  }
+  else
+  {
+    const char      * filename = RSTRING_PTR(_filename);
+    cairo_surface_t * surface  = get_snapshot_surface (_format)
+                                      (filename, canvas->width, canvas->height);
+    if (surface == NULL) {
+        rb_raise(rb_eArgError, "Failed to create %s surface for file %s\n", 
+           RSTRING_PTR(rb_inspect(_format)),
+           RSTRING_PTR(rb_inspect(_filename)));  // ERGO test this
+    }
+    else
+    {
+      cairo_t * waz_cr = canvas->cr;
+      cairo_t * cr     = canvas->cr = cairo_create (surface);
+      DRAW (self, canvas->app, block);
+      shoes_canvas_draw (self, self, Qfalse); // why, _why?
+      shoes_canvas_draw (self, self, Qtrue);
+      canvas->cr = waz_cr;
+      cairo_show_page (cr);
+      cairo_destroy (cr);
+      cairo_surface_destroy (surface);
+      //  TODO  detect cairo outrages here
+    }
+  }
+  return Qnil; //  TODO  what to return??
+}
diff --git a/shoes/canvas.h b/shoes/canvas.h
index 488586f..4d49ad7 100644
--- a/shoes/canvas.h
+++ b/shoes/canvas.h
@@ -376,6 +376,7 @@ VALUE shoes_canvas_window(int, VALUE *, VALUE);
 VALUE shoes_canvas_dialog(int, VALUE *, VALUE);
 VALUE shoes_canvas_window_plain(VALUE);
 VALUE shoes_canvas_dialog_plain(VALUE);
+VALUE shoes_canvas_snapshot(int, VALUE *, VALUE);
 
 VALUE shoes_slot_new(VALUE, VALUE, VALUE);
 VALUE shoes_flow_new(VALUE, VALUE);
diff --git a/shoes/ruby.h b/shoes/ruby.h
index 8820194..658ecef 100644
--- a/shoes/ruby.h
+++ b/shoes/ruby.h
@@ -207,6 +207,7 @@ void shoes_cairo_rect(cairo_t *, double, double, double, double, double);
   f("window", window, -1); \
   f("dialog", dialog, -1); \
   f("window_plain", window_plain, 0); \
-  f("dialog_plain", dialog_plain, 0)
+  f("dialog_plain", dialog_plain, 0); \
+  f("_snapshot", snapshot, -1)  /* TODO neg one?? */
 
 #endif

Attachment: simple-snapshot.rb
Description: application/ruby



Reply via email to