[cairo-commit] rcairo/packages/cairo/ext rb_cairo_surface.c, 1.12,
1.13
Kouhei Sutou
commit at pdx.freedesktop.org
Sun Oct 9 03:25:12 PDT 2005
Committed by: kou
Update of /cvs/cairo/rcairo/packages/cairo/ext
In directory gabe:/tmp/cvs-serv10771/packages/cairo/ext
Modified Files:
rb_cairo_surface.c
Log Message:
* packages/cairo/lib/cairo.rb: Removed deprecated wrapper API.
* packages/cairo/ext/rb_cairo_surface.c:
- Implemented File I/O API by Ruby.
- SurfaceXXX -> XXXSurface.
Index: rb_cairo_surface.c
===================================================================
RCS file: /cvs/cairo/rcairo/packages/cairo/ext/rb_cairo_surface.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- rb_cairo_surface.c 9 Oct 2005 07:04:40 -0000 1.12
+++ rb_cairo_surface.c 9 Oct 2005 10:25:09 -0000 1.13
@@ -22,11 +22,12 @@
VALUE rb_cCairo_Surface;
-VALUE rb_cCairo_SurfaceImage;
-VALUE rb_cCairo_SurfacePDF;
-VALUE rb_cCairo_SurfacePS;
+VALUE rb_cCairo_ImageSurface;
+VALUE rb_cCairo_PDFSurface;
+VALUE rb_cCairo_PSSurface;
-static ID cr_id_call;
+static ID cr_id_read;
+static ID cr_id_write;
static cairo_user_data_key_t klass_key;
#define _SELF (RVAL2CRSURFACE(self))
@@ -57,51 +58,112 @@
return klass;
}
+/* read/write callback */
+typedef struct cr_io_callback_closure {
+ VALUE target;
+ VALUE error;
+} cr_io_callback_closure_t;
+
+static VALUE
+cr_surface_io_func_rescue (VALUE io_closure)
+{
+ cr_io_callback_closure_t *closure;
+ closure = (cr_io_callback_closure_t *)io_closure;
+ closure->error = ruby_errinfo;
+ return Qnil;
+}
+
/* write callback */
-static cairo_status_t
-cr_surface_write_func (void *closure, const unsigned char *data, unsigned int length)
+static VALUE
+cr_surface_write_func_invoke (VALUE info)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- VALUE proc = (VALUE) closure;
+ VALUE output, data;
+ long written_bytes;
+ unsigned int length;
+
+ output = rb_ary_entry(info, 0);
+ data = rb_ary_entry(info, 1);
- if (!NIL_P(proc))
+ rb_funcall (output, cr_id_write, 1, data);
+ return Qnil;
+
+ length = RSTRING (data)->len;
+ while (length != 0)
{
- VALUE result;
- result = rb_funcall (proc, cr_id_call,
- rb_str_new ((const char *)data, length));
- status = NUM2INT (result);
- if (status != CAIRO_STATUS_SUCCESS && status != CAIRO_STATUS_WRITE_ERROR)
- status = CAIRO_STATUS_WRITE_ERROR;
+ VALUE rb_written_bytes = rb_funcall (output, cr_id_write, 1, data);
+ written_bytes = NUM2LONG (rb_written_bytes);
+ data = rb_str_substr (data, written_bytes,
+ RSTRING (data)->len - written_bytes);
+ length -= written_bytes;
}
- return status;
+ return Qnil;
}
-/* read callback */
static cairo_status_t
-cr_surface_read_func (void *closure, unsigned char *data, unsigned int length)
+cr_surface_write_func (void *write_closure,
+ const unsigned char *data, unsigned int length)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- VALUE proc = (VALUE)closure;
+ cr_io_callback_closure_t *closure;
+ VALUE args;
+
+ closure = (cr_io_callback_closure_t *)write_closure;
+ args = rb_ary_new3 (2,
+ closure->target,
+ rb_str_new ((const char *)data, length));
+ rb_rescue2 (cr_surface_write_func_invoke, args,
+ cr_surface_io_func_rescue, (VALUE) closure, rb_eException,
+ (VALUE)0);
- if (!NIL_P(proc))
- {
- VALUE result, read_data;
- result = rb_funcall (proc, cr_id_call, INT2NUM (length));
- status = NUM2INT (rb_ary_entry (result, 0));
- read_data = rb_ary_entry (result, 1);
- if ((status != CAIRO_STATUS_SUCCESS &&
- status != CAIRO_STATUS_READ_ERROR) ||
- RSTRING (read_data)->len != length)
- status = CAIRO_STATUS_READ_ERROR;
+ if (NIL_P (closure->error))
+ return CAIRO_STATUS_SUCCESS;
+ else
+ return CAIRO_STATUS_WRITE_ERROR;
+}
- if (!status)
- memcpy (data, StringValuePtr (read_data), length);
- }
+/* read callback */
+static VALUE
+cr_surface_read_func_invoke (VALUE info)
+{
+ VALUE input, result;
+ unsigned int length, rest;
+ unsigned char *data;
- return status;
+ input = rb_ary_entry (info, 0);
+ length = NUM2UINT (rb_ary_entry (info, 1));
+ data = (unsigned char *) rb_ary_entry (info, 2);
+
+ result = rb_str_new2 ("");
+ rest = length;
+
+ for (rest = length; rest != 0; rest = length - RSTRING (result)->len)
+ {
+ rb_str_concat (result, rb_funcall (input, cr_id_read, 1, INT2NUM (rest)));
+ }
+
+ memcpy ((void *)data, (const void *)StringValuePtr (result), length);
+
+ return Qnil;
}
+static cairo_status_t
+cr_surface_read_func (void *read_closure,
+ unsigned char *data, unsigned int length)
+{
+ cr_io_callback_closure_t *closure;
+ VALUE args;
+
+ closure = (cr_io_callback_closure_t *)read_closure;
+ args = rb_ary_new3 (3, closure->target, UINT2NUM (length), (VALUE) data);
+ rb_rescue2 (cr_surface_read_func_invoke, args,
+ cr_surface_io_func_rescue, (VALUE) closure, rb_eException,
+ (VALUE)0);
+
+ if (NIL_P (closure->error))
+ return CAIRO_STATUS_SUCCESS;
+ else
+ return CAIRO_STATUS_READ_ERROR;
+}
/* constructor/de-constructor */
cairo_surface_t *
@@ -180,33 +242,49 @@
#if CAIRO_HAS_PNG_FUNCTIONS
static VALUE
-cr_surface_write_to_png (int argc, VALUE *argv, VALUE self)
+cr_surface_write_to_png_stream (VALUE self, VALUE target)
{
cairo_status_t status;
- VALUE filename;
- int n;
+ cr_io_callback_closure_t closure;
- n = rb_scan_args (argc, argv, "01", &filename);
+ closure.target = target;
+ closure.error = Qnil;
+
+ status = cairo_surface_write_to_png_stream (_SELF, cr_surface_write_func,
+ (void *)&closure);
+ if (!NIL_P (closure.error))
+ rb_exc_raise (closure.error);
- if (n == 0 && rb_block_given_p ())
- {
- status = cairo_surface_write_to_png_stream (_SELF,
- cr_surface_write_func,
- (void *)rb_block_proc());
- }
- else if (n == 1 && TYPE(filename) == T_STRING)
- {
- status = cairo_surface_write_to_png (_SELF, StringValuePtr (filename));
- }
- else
- {
- rb_raise (rb_eArgError,
- "invalid argument (expect (filename) or (&block))");
- }
-
rb_cairo_check_status (status);
return self;
}
+
+static VALUE
+cr_surface_write_to_png_stream_invoke (VALUE info)
+{
+ return cr_surface_write_to_png_stream (rb_ary_entry (info, 0),
+ rb_ary_entry (info, 1));
+}
+
+static VALUE
+cr_surface_write_to_png (VALUE self, VALUE filename)
+{
+ VALUE info, file;
+
+ file = rb_file_open (StringValuePtr (filename), "wb");
+ info = rb_ary_new3 (2, self, file);
+ return rb_ensure (cr_surface_write_to_png_stream_invoke, info,
+ rb_io_close, file);
+}
+
+static VALUE
+cr_surface_write_to_png_generic (VALUE self, VALUE target)
+{
+ if (rb_respond_to (target, cr_id_write))
+ return cr_surface_write_to_png_stream (self, target);
+ else
+ return cr_surface_write_to_png (self, target);
+}
#endif
static VALUE
@@ -301,16 +379,31 @@
}
#if CAIRO_HAS_PNG_FUNCTIONS
-static cairo_surface_t *
-cr_surface_image_create_from_png (VALUE self, VALUE filename)
+static VALUE
+cr_surface_image_create_from_png_stream (VALUE target)
{
- return cairo_image_surface_create_from_png (StringValuePtr (filename));
+ cr_io_callback_closure_t closure;
+ cairo_surface_t *surface;
+
+ closure.target = target;
+ closure.error = Qnil;
+
+ surface = cairo_image_surface_create_from_png_stream (cr_surface_read_func,
+ (void *)&closure);
+ if (!NIL_P (closure.error))
+ rb_exc_raise (closure.error);
+
+ return (VALUE)surface;
}
-static cairo_surface_t *
-cr_surface_image_create_from_png_stream (VALUE self)
+
+static VALUE
+cr_surface_image_create_from_png (VALUE filename)
{
- return cairo_image_surface_create_from_png_stream (cr_surface_read_func,
- (void *)rb_block_proc());
+ VALUE file;
+ file = rb_file_open (StringValuePtr (filename), "rb");
+
+ return rb_ensure (cr_surface_image_create_from_png_stream, file,
+ rb_io_close, file);
}
#endif
@@ -321,7 +414,7 @@
VALUE arg1, arg2, arg3, arg4, arg5;
int n;
- n = rb_scan_args (argc, argv, "32", &arg1, &arg2, &arg3, &arg4, &arg5);
+ n = rb_scan_args (argc, argv, "14", &arg1, &arg2, &arg3, &arg4, &arg5);
if (n == 3)
surface = cr_surface_image_create (self, arg1, arg2, arg3);
@@ -329,20 +422,19 @@
surface =
cr_surface_image_create_for_data (self, arg1, arg2, arg3, arg4, arg5);
#if CAIRO_HAS_PNG_FUNCTIONS
- else if (n == 0 && rb_block_given_p ())
- surface =
- cr_surface_image_create_from_png_stream (self);
+ else if (n == 1 && rb_respond_to (arg1, cr_id_read))
+ surface = (cairo_surface_t *)cr_surface_image_create_from_png_stream (arg1);
else if (n == 1)
- surface = cr_surface_image_create_from_png (self, arg1);
+ surface = (cairo_surface_t *)cr_surface_image_create_from_png (arg1);
#endif
else
rb_raise (rb_eArgError,
"invalid argument (expect "
#if CAIRO_HAS_PNG_FUNCTIONS
- "(&block), (filename) "
+ "(input), (filename), "
#endif
"(format, width, height) or "
- "(data format width height stride))");
+ "(data, format, width, height, stride))");
cr_surface_check_status (surface);
DATA_PTR (self) = surface;
@@ -361,47 +453,64 @@
return INT2NUM (cairo_image_surface_get_height (_SELF));
}
-
#if CAIRO_HAS_PS_SURFACE
/* PS-surface functions */
-static cairo_surface_t *
-cr_surface_ps_create (VALUE self, VALUE filename,
- VALUE width_in_points, VALUE height_in_points)
+static VALUE
+cr_surface_ps_create_for_stream (VALUE info)
{
- return cairo_ps_surface_create (StringValuePtr (filename),
- NUM2DBL (width_in_points),
- NUM2DBL (height_in_points));
+ VALUE self, input, width_in_points, height_in_points;
+ cr_io_callback_closure_t closure;
+ cairo_surface_t *surface;
+
+ self = rb_ary_entry (info, 0);
+ input = rb_ary_entry (info, 1);
+ width_in_points = rb_ary_entry (info, 2);
+ height_in_points = rb_ary_entry (info, 3);
+
+ closure.target = input;
+ closure.error = Qnil;
+
+ surface = cairo_ps_surface_create_for_stream (cr_surface_write_func,
+ (void *) &closure,
+ NUM2DBL (width_in_points),
+ NUM2DBL (height_in_points));
+ if (!NIL_P (closure.error))
+ rb_exc_raise (closure.error);
+
+ return (VALUE)surface;
}
-static cairo_surface_t *
-cr_surface_ps_create_for_stream (VALUE self,
- VALUE width_in_points, VALUE height_in_points)
+static VALUE
+cr_surface_ps_create (VALUE self, VALUE filename,
+ VALUE width_in_points, VALUE height_in_points)
{
- return cairo_ps_surface_create_for_stream (cr_surface_write_func,
- (void *) ruby_block,
- NUM2DBL (width_in_points),
- NUM2DBL (height_in_points));
+ VALUE file, info;
+
+ file = rb_file_open (StringValuePtr (filename), "rb");
+ info = rb_ary_new3 (4, self, file, width_in_points, height_in_points);
+ return rb_ensure (cr_surface_ps_create_for_stream, info,
+ rb_io_close, file);
}
static VALUE
-cr_surface_ps_initialize (int argc, VALUE *argv, VALUE self)
+cr_surface_ps_initialize (VALUE self, VALUE target,
+ VALUE width_in_points, VALUE height_in_points)
{
cairo_surface_t *surface;
- VALUE arg1, arg2, arg3;
- int n;
- n = rb_scan_args (argc, argv, "21", &arg1, &arg2, &arg3);
-
- if (n == 2 && rb_block_given_p ())
- surface = cr_surface_ps_create_for_stream (self, arg1, arg2);
- else if (n == 3)
- surface = cr_surface_ps_create (self, arg1, arg2, arg3);
+ if (rb_respond_to (target, cr_id_read))
+ {
+ VALUE info;
+ info = rb_ary_new3 (4, self, target, width_in_points, height_in_points);
+ surface = (cairo_surface_t *)cr_surface_ps_create_for_stream (info);
+ }
else
- rb_raise (rb_eArgError,
- "invalid argument (expect "
- "(width_in_points, height_in_points, &block) or "
- "(filename, width_in_points, height_in_points))");
-
+ {
+ surface = (cairo_surface_t *)cr_surface_ps_create (self, target,
+ width_in_points,
+ height_in_points);
+ }
+
cr_surface_check_status (surface);
DATA_PTR (self) = surface;
return Qnil;
@@ -418,44 +527,62 @@
#if CAIRO_HAS_PDF_SURFACE
/* PDF-surface functions */
-static cairo_surface_t *
-cr_surface_pdf_create (VALUE self, VALUE filename,
- VALUE width_in_points, VALUE height_in_points)
+static VALUE
+cr_surface_pdf_create_for_stream (VALUE info)
{
- return cairo_pdf_surface_create (StringValuePtr (filename),
- NUM2DBL (width_in_points),
- NUM2DBL (height_in_points));
+ VALUE self, input, width_in_points, height_in_points;
+ cr_io_callback_closure_t closure;
+ cairo_surface_t *surface;
+
+ self = rb_ary_entry (info, 0);
+ input = rb_ary_entry (info, 1);
+ width_in_points = rb_ary_entry (info, 2);
+ height_in_points = rb_ary_entry (info, 3);
+
+ closure.target = input;
+ closure.error = Qnil;
+
+ surface = cairo_pdf_surface_create_for_stream (cr_surface_write_func,
+ (void *) &closure,
+ NUM2DBL (width_in_points),
+ NUM2DBL (height_in_points));
+ if (!NIL_P (closure.error))
+ rb_exc_raise (closure.error);
+
+ return (VALUE)surface;
}
-static cairo_surface_t *
-cr_surface_pdf_create_for_stream (VALUE self,
- VALUE width_in_points, VALUE height_in_points)
+static VALUE
+cr_surface_pdf_create (VALUE self, VALUE filename,
+ VALUE width_in_points, VALUE height_in_points)
{
- return cairo_pdf_surface_create_for_stream (cr_surface_write_func,
- (void *) ruby_block,
- NUM2DBL (width_in_points),
- NUM2DBL (height_in_points));
+ VALUE file, info;
+
+ file = rb_file_open (StringValuePtr (filename), "rb");
+ info = rb_ary_new3 (4, self, file, width_in_points, height_in_points);
+ return rb_ensure (cr_surface_pdf_create_for_stream, info,
+ rb_io_close, file);
}
static VALUE
-cr_surface_pdf_initialize (int argc, VALUE *argv, VALUE self)
+cr_surface_pdf_initialize (VALUE self, VALUE target,
+ VALUE width_in_points, VALUE height_in_points)
{
cairo_surface_t *surface;
- VALUE arg1, arg2, arg3;
- int n;
- n = rb_scan_args (argc, argv, "21", &arg1, &arg2, &arg3);
-
- if (n == 2 && rb_block_given_p ())
- surface = cr_surface_pdf_create_for_stream (self, arg1, arg2);
- else if (n == 3)
- surface = cr_surface_pdf_create (self, arg1, arg2, arg3);
+ if (rb_respond_to (target, cr_id_read))
+ {
+ VALUE info;
+ info = rb_ary_new3 (4, self, target, width_in_points, height_in_points);
+ surface = (cairo_surface_t *)cr_surface_pdf_create_for_stream (info);
+ }
else
- rb_raise (rb_eArgError,
- "invalid argument (expect "
- "(width_in_points, height_in_points, &block) or "
- "(filename, width_in_points, height_in_points))");
-
+ {
+ surface = (cairo_surface_t *)cr_surface_pdf_create (self, target,
+ width_in_points,
+ height_in_points);
+ }
+
cr_surface_check_status (surface);
DATA_PTR (self) = surface;
return Qnil;
@@ -473,7 +600,8 @@
void
Init_cairo_surface (void)
{
- cr_id_call = rb_intern ("call");
+ cr_id_read = rb_intern ("read");
+ cr_id_write = rb_intern ("write");
rb_cCairo_Surface =
rb_define_class_under (rb_mCairo, "Surface", rb_cObject);
@@ -486,7 +614,7 @@
#if CAIRO_HAS_PNG_FUNCTIONS
rb_define_method (rb_cCairo_Surface, "write_to_png",
- cr_surface_write_to_png, -1);
+ cr_surface_write_to_png_generic, 1);
#endif
@@ -498,37 +626,37 @@
cr_surface_set_device_offset, 2);
/* Image-surface */
- rb_cCairo_SurfaceImage =
- rb_define_class_under (rb_mCairo, "SurfaceImage", rb_cCairo_Surface);
+ rb_cCairo_ImageSurface =
+ rb_define_class_under (rb_mCairo, "ImageSurface", rb_cCairo_Surface);
- rb_define_method (rb_cCairo_SurfaceImage, "initialize",
+ rb_define_method (rb_cCairo_ImageSurface, "initialize",
cr_surface_image_initialize, -1);
- rb_define_method (rb_cCairo_SurfaceImage, "width",
+ rb_define_method (rb_cCairo_ImageSurface, "width",
cr_surface_image_get_width, 0);
- rb_define_method (rb_cCairo_SurfaceImage, "height",
+ rb_define_method (rb_cCairo_ImageSurface, "height",
cr_surface_image_get_height, 0);
#if CAIRO_HAS_PS_SURFACE
/* PS-surface */
- rb_cCairo_SurfacePS =
- rb_define_class_under (rb_mCairo, "SurfacePS", rb_cCairo_Surface);
+ rb_cCairo_PSSurface =
+ rb_define_class_under (rb_mCairo, "PSSurface", rb_cCairo_Surface);
- rb_define_method (rb_cCairo_SurfacePS, "initialize",
- cr_surface_ps_initialize, -1);
- rb_define_method (rb_cCairo_SurfacePS, "set_dpi",
+ rb_define_method (rb_cCairo_PSSurface, "initialize",
+ cr_surface_ps_initialize, 3);
+ rb_define_method (rb_cCairo_PSSurface, "set_dpi",
cr_surface_ps_set_dpi, 2);
#endif
#if CAIRO_HAS_PDF_SURFACE
/* PDF-surface */
- rb_cCairo_SurfacePDF =
- rb_define_class_under (rb_mCairo, "SurfacePDF", rb_cCairo_Surface);
+ rb_cCairo_PDFSurface =
+ rb_define_class_under (rb_mCairo, "PDFSurface", rb_cCairo_Surface);
- rb_define_method (rb_cCairo_SurfacePDF, "initialize",
- cr_surface_pdf_initialize, -1);
- rb_define_method (rb_cCairo_SurfacePDF, "set_dpi",
+ rb_define_method (rb_cCairo_PDFSurface, "initialize",
+ cr_surface_pdf_initialize, 3);
+ rb_define_method (rb_cCairo_PDFSurface, "set_dpi",
cr_surface_pdf_set_dpi, 2);
#endif
}
More information about the cairo-commit
mailing list