[cairo-commit] rcairo/packages/cairo/ext rb_cairo_surface.c, 1.6,
1.7
Kouhei Sutou
commit at pdx.freedesktop.org
Fri Oct 7 06:05:53 PDT 2005
Committed by: kou
Update of /cvs/cairo/rcairo/packages/cairo/ext
In directory gabe:/tmp/cvs-serv29037/packages/cairo/ext
Modified Files:
rb_cairo_surface.c
Log Message:
* packages/cairo/ext/rb_cairo_surface.c: Implemented
cairo_surface_t.
Index: rb_cairo_surface.c
===================================================================
RCS file: /cvs/cairo/rcairo/packages/cairo/ext/rb_cairo_surface.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- rb_cairo_surface.c 13 Sep 2005 16:22:29 -0000 1.6
+++ rb_cairo_surface.c 7 Oct 2005 13:05:51 -0000 1.7
@@ -11,46 +11,81 @@
#include "rb_cairo.h"
#include "rubyio.h"
-#ifdef CAIRO_HAS_PDF_SURFACE
-#include <cairo-pdf.h>
+#if CAIRO_HAS_PS_SURFACE
+#include <cairo-ps.h>
#endif
-#ifdef CAIRO_HAS_PNG_SURFACE
-#include <cairo-png.h>
+#if CAIRO_HAS_PDF_SURFACE
+#include <cairo-pdf.h>
#endif
-#ifdef CAIRO_HAS_PS_SURFACE
-#include <cairo-ps.h>
-#endif
VALUE rb_cCairo_Surface;
+VALUE rb_cCairo_SurfaceImage;
+VALUE rb_cCairo_SurfacePDF;
+VALUE rb_cCairo_SurfacePS;
+
+static ID cr_id_call;
#define _SELF (RVAL2CRSURFACE(self))
+static inline void
+cr_surface_check_status (cairo_surface_t *surface)
+{
+ cairo_status_t status;
+ status = cairo_surface_status (surface);
+ if (status)
+ {
+ rb_cairo_raise_exception (status);
+ }
+}
+
+/* write callback */
static cairo_status_t
-rfile_write (void *closure,
- const char *data,
- unsigned int length)
+cr_surface_write_func (void *closure, const unsigned char *data, unsigned int length)
{
- OpenFile *fptr;
- FILE *fp;
-
- fptr = closure;
- fp = GetWriteFile (fptr);
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ VALUE proc = (VALUE) closure;
- if (rb_io_fwrite (data, length, fp) == length)
- return CAIRO_STATUS_SUCCESS;
- return CAIRO_STATUS_WRITE_ERROR;
+ if (!NIL_P(proc))
+ {
+ VALUE result;
+ result = rb_funcall (proc, cr_id_call, rb_str_new (data, length));
+ status = NUM2INT (result);
+ if (status != CAIRO_STATUS_SUCCESS && status != CAIRO_STATUS_WRITE_ERROR)
+ status = CAIRO_STATUS_WRITE_ERROR;
+ }
+
+ return status;
}
-static void
-rfile_destroy_closure (void *closure)
+/* read callback */
+static cairo_status_t
+cr_surface_read_func (void *closure, unsigned char *data, unsigned int length)
{
- OpenFile *fptr;
-
- fptr = closure;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ VALUE proc = (VALUE)closure;
+
+ 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 (!status)
+ memcpy (data, StringValuePtr (read_data), length);
+ }
+
+ return status;
}
+
+/* constructor/de-constructor */
cairo_surface_t *
rb_cairo_surface_from_ruby_object (VALUE obj)
{
@@ -73,12 +108,12 @@
}
VALUE
-rb_cairo_surface_to_ruby_object (cairo_surface_t *surface)
+rb_cairo_surface_to_ruby_object (cairo_surface_t *surface, VALUE klass)
{
if (surface)
{
cairo_surface_reference (surface);
- return Data_Wrap_Struct (rb_cCairo_Surface, NULL, cr_surface_free, surface);
+ return Data_Wrap_Struct (klass, NULL, cr_surface_free, surface);
}
else
{
@@ -86,236 +121,367 @@
}
}
-static VALUE
-rb_cairo_surface_new (VALUE klass,
- VALUE format_v,
- VALUE width_v, VALUE height_v)
+static VALUE
+cr_surface_allocate (VALUE klass)
+{
+ return Data_Wrap_Struct (klass, NULL, cr_surface_free, NULL);
+}
+
+/* Surface manipulation */
+static VALUE
+cr_surface_create_similar (VALUE self, VALUE content, VALUE width, VALUE height)
{
cairo_surface_t *surface;
- int format;
- int width;
- int height;
+ surface = cairo_create_similar (RVAL2CRSURFACE (self),
+ NUM2INT (content),
+ NUM2DBL (width),
+ NUM2DBL (height));
+ cr_surface_check_status (surface);
+ return CRSURFACE2RVAL (surface, rb_obj_class (self));
+}
- format = NUM2INT (format_v);
- width = NUM2INT (width_v);
- height = NUM2INT (height_v);
+static VALUE
+cairo_surface_finish (VALUE self)
+{
+ cairo_surface_finish (_SELF);
+ cr_surface_check_status (_SELF);
+ return self;
+}
- if (format < CAIRO_FORMAT_ARGB32 || format > CAIRO_FORMAT_A1)
- {
- rb_raise (rb_eArgError, "invalid bitmap format");
- }
- if (width < 0)
- {
- rb_raise (rb_eArgError, "width must be positive");
- }
- if (height < 0)
+#if CAIRO_HAS_PNG_FUNCTIONS
+static VALUE
+cr_surface_write_to_png (int argc, VALUE *argv, VALUE self)
+{
+ cairo_status_t status;
+ VALUE filename;
+ int n;
+
+ n = rb_scan_args (argc, argv, "01", &filename);
+
+ if (n == 0)
{
- rb_raise (rb_eArgError, "height must be positive");
+ rb_need_block();
+ status = cairo_surface_write_to_png_stream (_SELF,
+ cr_surface_write_func,
+ (void *)ruby_block);
}
-
- surface =
- cairo_image_surface_create ((cairo_format_t) format, width, height);
- if (surface)
+ else if (TYPE(filename) != T_STRING || )
{
- VALUE rb_surface = CRSURFACE2RVAL (surface);
- cairo_surface_destroy (surface);
- return rb_surface;
+ rb_raise (rb_eArgError,
+ "invalid argument (expect (filename) or (&block))");
}
else
{
- rb_raise (rb_eNoMemError, "unable to allocate surface");
- return Qundef;
+ status = cairo_surface_write_to_png (_SELF, StringValuePtr (filiename));
}
+
+ rb_cairo_raise_exception (status);
+ return self;
}
+#endif
-
-#if XXXCAIRO_HAS_PDF_SURFACE
-static VALUE
-rb_cairo_surface_new_pdf (VALUE klass,
- VALUE port,
- VALUE width_inches_v, VALUE height_inches_v,
- VALUE x_pixels_per_inch_v, VALUE y_pixels_per_inch_v)
+static VALUE
+cr_surface_get_font_options (VALUE self)
{
- cairo_surface_t *surface;
- double width_inches;
- double height_inches;
- double x_pixels_per_inch;
- double y_pixels_per_inch;
+ cairo_font_options_t options;
+ cairo_surface_get_font_options (_SELF, &options);
+ cr_surface_check_status (_SELF);
+ return CRFONTOPTIONS2RVAL (cairo_font_options_copy (&options)); /* check status!*/
+}
- Check_Type (port, T_FILE);
- rb_io_check_writable (RFILE (port)->fptr);
+static VALUE
+cr_surface_flush (VALUE self)
+{
+ cairo_surface_flush (_SELF);
+ cr_surface_check_status (_SELF);
+ return self;
+}
- width_inches = NUM2DBL (width_inches_v);
- height_inches = NUM2DBL (height_inches_v);
- x_pixels_per_inch = NUM2DBL (x_pixels_per_inch_v);
- y_pixels_per_inch = NUM2DBL (y_pixels_per_inch_v);
+static VALUE
+cr_surface_mark_dirty (int argc, VALUE *argv, VALUE self)
+{
+ VALUE x, y, width, height;
+ int n;
+
+ n = rb_scan_args (argc, argv, "04", &x, &y, &width, &height);
- if (width_inches < 0)
- {
- rb_raise (rb_eArgError, "width_inches must be positive");
- }
- if (height_inches < 0)
+ if (n == 0)
{
- rb_raise (rb_eArgError, "height_inches must be positive");
+ cairo_surface_mark_dirty (_SELF);
}
-#if 1
- surface = cairo_pdf_surface_create (rfile_write, rfile_destroy_closure, RFILE (port)->fptr,
- width_inches, height_inches,
- x_pixels_per_inch, y_pixels_per_inch);
-#endif
-#if 0
- surface = cairo_pdf_surface_create_for_file (GetWriteFile(RFILE (port)->fptr),
- width_inches, height_inches,
- x_pixels_per_inch, y_pixels_per_inch);
-#endif
-
- if (surface)
+ else if (n == 4)
{
- return Data_Wrap_Struct (rb_cCairo_Surface, NULL, rb_free_surface,
- surface);
+ cairo_surface_mark_dirty_rectangle (_SELF,
+ NUM2INT (x), NUM2INT (y),
+ NUM2INT (width), NUM2INT (height));
}
else
{
- rb_raise (rb_eNoMemError, "unable to allocate surface");
- return Qundef;
+ rb_raise (rb_eArgError,
+ "invalid argument (expect () or (x, y, width, height))");
}
+
+ cr_surface_check_status (_SELF);
+ return self;
+}
+
+static VALUE
+cr_surface_set_device_offset (VALUE self, VALUE x_offset, VALUE y_offset)
+{
+ cairo_surface_set_device_offset (_SELF,
+ NUM2DBL (x_offset),
+ NUM2DBL (y_offset));
+ cr_surface_check_status (_SELF);
+ return self;
+}
+
+
+/* Image-surface functions */
+static cairo_surface_t *
+cr_surface_image_create (VALUE self, VALUE format, VALUE width, VALUE height)
+{
+ return cairo_image_surface_create (NUM2INT (format),
+ NUM2INT (width),
+ NUM2INT (height));
+}
+
+static cairo_surface_t *
+cr_surface_image_create_for_data (VALUE self, VALUE data, VALUE format,
+ VALUE width, VALUE height, VALUE stride)
+{
+ return cairo_image_surface_create_for_data (StringValuePtr (data),
+ NUM2INT (format),
+ NUM2INT (width),
+ NUM2INT (height),
+ NUM2INT (stride));
+}
+
+#if CAIRO_HAS_PNG_FUNCTIONS
+static cairo_surface_t *
+cr_surface_image_create_from_png (VALUE self, VALUE filename)
+{
+ return cairo_image_surface_create_from_png (StringValuePtr (filename));
+}
+static cairo_surface_t *
+cr_surface_image_create_from_png_stream (VALUE self)
+{
+ return cairo_image_surface_create_from_png_stream (cr_surface_read_func,
+ (void *)ruby_block);
}
#endif
-static VALUE
-rb_cairo_surface_finish (VALUE self)
+static VALUE
+cr_surface_image_initialize (int argc, VALUE *argv, VALUE self)
{
- cairo_surface_finish (_SELF);
+ cairo_surface_t *surface;
+ VALUE arg1, arg2, arg3, arg4, arg5;
+ int n;
+
+ n = rb_scan_args (argc, argv, "32", &arg1, &arg2, &arg3, &arg4, &arg5);
+
+ if (n == 3)
+ surface = cr_surface_image_create (self, arg1, arg2, arg3);
+ else if (n == 5)
+ 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)
+ surface = cr_surface_image_create_from_png (self, arg1);
+#endif
+ else
+ rb_raise (rb_eArgError,
+ "invalid argument (expect "
+#if CAIRO_HAS_PNG_FUNCTIONS
+ "(&block), (filename) "
+#endif
+ "(format, width, height) or "
+ "(data format width height stride))");
+
+ cr_surface_check_status (surface);
+ DATA_PTR (self) = surface;
return Qnil;
}
-#ifdef CAIRO_HAS_PNG_SURFACE
-static VALUE
-rb_cairo_surface_new_png (VALUE klass,
- VALUE port,
- VALUE format_v,
- VALUE width_v, VALUE height_v)
+static VALUE
+cr_surface_image_get_width (VALUE self)
{
- cairo_surface_t *surface;
- int format;
- int width;
- int height;
+ return INT2NUM (cairo_image_surface_get_width (_SELF));
+}
- Check_Type (port, T_FILE);
- rb_io_check_writable (RFILE (port)->fptr);
+static VALUE
+cr_surface_image_get_height (VALUE self)
+{
+ return INT2NUM (cairo_image_surface_get_height (_SELF));
+}
- format = NUM2INT (format_v);
- width = NUM2INT (width_v);
- height = NUM2INT (height_v);
- if (format < CAIRO_FORMAT_ARGB32 || format > CAIRO_FORMAT_A1)
- {
- rb_raise (rb_eArgError, "invalid bitmap format");
- }
- if (width < 0)
- {
- rb_raise (rb_eArgError, "width must be positive");
- }
- if (height < 0)
- {
- rb_raise (rb_eArgError, "height must be positive");
- }
+#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)
+{
+ return cairo_ps_surface_create (StringValuePtr (filename),
+ NUM2DBL (width_in_points),
+ NUM2DBL (height_in_points));
+}
- surface =
- cairo_png_surface_create (GetWriteFile (RFILE (port)->fptr),
- (cairo_format_t) format, width, height);
- if (surface)
- {
- return Data_Wrap_Struct (rb_cCairo_Surface, NULL, rb_free_surface,
- surface);
- }
- else
- {
- rb_raise (rb_eNoMemError, "unable to allocate surface");
- return Qundef;
- }
+static cairo_surface_t *
+cr_surface_ps_create_for_stream (VALUE self,
+ 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));
}
-#endif
-#ifdef XXXCAIRO_HAS_PS_SURFACE
-static VALUE
-rb_cairo_surface_new_ps (VALUE klass,
- VALUE port,
- VALUE width_inches_v, VALUE height_inches_v,
- VALUE x_pixels_per_inch_v, VALUE y_pixels_per_inch_v)
+static VALUE
+cr_surface_ps_initialize (int argc, VALUE *argv, VALUE self)
{
cairo_surface_t *surface;
- double width_inches;
- double height_inches;
- double x_pixels_per_inch;
- double y_pixels_per_inch;
+ VALUE arg1, arg2, arg3;
+ int n;
+
+ n = rb_scan_args (argc, argv, "21", &arg1, &arg2, &arg3);
- Check_Type (port, T_FILE);
- rb_io_check_writable (RFILE (port)->fptr);
+ 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);
+ else
+ rb_raise (rb_eArgError,
+ "invalid argument (expect "
+ "(width_in_points, height_in_points, &block) or "
+ "(filename, width_in_points, height_in_points))");
- width_inches = NUM2DBL (width_inches_v);
- height_inches = NUM2DBL (height_inches_v);
- x_pixels_per_inch = NUM2DBL (x_pixels_per_inch_v);
- y_pixels_per_inch = NUM2DBL (y_pixels_per_inch_v);
+ cr_surface_check_status (surface);
+ DATA_PTR (self) = surface;
+ return Qnil;
+}
- if (width_inches < 0)
- {
- rb_raise (rb_eArgError, "width_inches must be positive");
- }
- if (height_inches < 0)
- {
- rb_raise (rb_eArgError, "height_inches must be positive");
- }
+static VALUE
+cr_surface_ps_set_dpi (VALUE self, VALUE x_dpi, VALUE y_dpi)
+{
+ cairo_ps_surface_set_dpi (_SELF, NUM2DBL (x_dpi), NUM2DBL (y_dpi));
+ cr_surface_check_status (_SELF);
+ return self;
+}
+#endif
- surface = cairo_ps_surface_create (GetWriteFile (RFILE (port)->fptr),
- width_inches, height_inches,
- x_pixels_per_inch, y_pixels_per_inch);
- if (surface)
- {
- return Data_Wrap_Struct (rb_cCairo_Surface, NULL, rb_free_surface,
- surface);
- }
+#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)
+{
+ return cairo_pdf_surface_create (StringValuePtr (filename),
+ NUM2DBL (width_in_points),
+ NUM2DBL (height_in_points));
+}
+
+static cairo_surface_t *
+cr_surface_pdf_create_for_stream (VALUE self,
+ 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));
+}
+
+static VALUE
+cr_surface_pdf_initialize (int argc, VALUE *argv, VALUE self)
+{
+ 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);
else
- {
- rb_raise (rb_eNoMemError, "unable to allocate surface");
- return Qundef;
- }
+ rb_raise (rb_eArgError,
+ "invalid argument (expect "
+ "(width_in_points, height_in_points, &block) or "
+ "(filename, width_in_points, height_in_points))");
+
+ cr_surface_check_status (surface);
+ DATA_PTR (self) = surface;
+ return Qnil;
}
-#endif
static VALUE
-rb_cairo_surface_write_to_png (VALUE self,
- VALUE filename_v)
+cr_surface_pdf_set_dpi (VALUE self, VALUE x_dpi, VALUE y_dpi)
{
- cairo_surface_write_to_png (_SELF, STR2CSTR (filename_v));
+ cairo_pdf_surface_set_dpi (_SELF, NUM2DBL (x_dpi), NUM2DBL (y_dpi));
+ cr_surface_check_status (_SELF);
return self;
}
+#endif
void
Init_cairo_surface (void)
{
+ cr_id_call = rb_intern ("call");
+
rb_cCairo_Surface =
rb_define_class_under (rb_mCairo, "Surface", rb_cObject);
- rb_define_singleton_method (rb_cCairo_Surface, "new",
- RUBY_METHOD_FUNC (rb_cairo_surface_new), 3);
+ rb_define_alloc_func (rb_cCairo_Surface, cr_surface_allocate);
+
+ rb_define_method (rb_cCairo_Surface, "create_similar",
+ cr_surface_create_similar, 3);
+
+#if CAIRO_HAS_PNG_FUNCTIONS
rb_define_method (rb_cCairo_Surface, "write_to_png",
- RUBY_METHOD_FUNC (rb_cairo_surface_write_to_png), 1);
- rb_define_method (rb_cCairo_Surface, "finish",
- RUBY_METHOD_FUNC (rb_cairo_surface_finish), 0);
-
-#if XXXCAIRO_HAS_PDF_SURFACE
- rb_define_singleton_method (rb_cCairo_Surface, "new_pdf",
- RUBY_METHOD_FUNC (rb_cairo_surface_new_pdf), 5);
+ cr_surface_write_to_png, -1);
#endif
+
+ rb_define_method (rb_cCairo_Surface, "font_options",
+ cr_surface_get_font_options, 0);
+ rb_define_method (rb_cCairo_Surface, "mark_dirty", cr_surface_mark_dirty, 0);
+ rb_define_method (rb_cCairo_Surface, "set_device_offset",
+ cr_surface_set_device_offset, 2);
-#ifdef CAIRO_HAS_PNG_SURFACE
- rb_define_singleton_method (rb_cCairo_Surface, "new_png",
- RUBY_METHOD_FUNC (rb_cairo_surface_new_png), 4);
+ /* Image-surface */
+ rb_cCairo_SurfaceImage =
+ rb_define_class_under (rb_mCairo, "SurfaceImage", rb_cCairo_Surface);
+
+ rb_define_method (rb_cCairo_SurfaceImage, "initialize",
+ cr_surface_image_initialize, -1);
+
+ rb_define_method (rb_cCairo_SurfaceImage, "width",
+ cr_surface_image_get_width, 0);
+ rb_define_method (rb_cCairo_SurfaceImage, "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_define_method (rb_cCairo_SurfacePS, "initialize",
+ cr_surface_ps_initialize, -1);
+ rb_define_method (rb_cCairo_SurfacePS, "set_dpi",
+ cr_surface_ps_set_dpi, 2);
#endif
-#ifdef XXXCAIRO_HAS_PS_SURFACE
- rb_define_singleton_method (rb_cCairo_Surface, "new_ps",
- RUBY_METHOD_FUNC (rb_cairo_surface_new_ps), 5);
+#if CAIRO_HAS_PDF_SURFACE
+ /* PDF-surface */
+ rb_cCairo_SurfacePDF =
+ rb_define_class_under (rb_mCairo, "SurfacePDF", rb_cCairo_Surface);
+
+ rb_define_method (rb_cCairo_SurfacePDF, "initialize",
+ cr_surface_pdf_initialize, -1);
+ rb_define_method (rb_cCairo_SurfacePDF, "set_dpi",
+ cr_surface_pdf_set_dpi, 2);
#endif
}
More information about the cairo-commit
mailing list