[cairo-commit] rcairo/src cairo.def, 1.16, 1.17 rb_cairo.h, 1.21, 1.22 rb_cairo_context.c, 1.27, 1.28 rb_cairo_exception.c, 1.3, 1.4 rb_cairo_font_face.c, 1.5, 1.6 rb_cairo_private.c, 1.8, 1.9 rb_cairo_private.h, 1.11, 1.12 rb_cairo_surface.c, 1.40, 1.41
Kouhei Sutou
commit at pdx.freedesktop.org
Sat Aug 16 05:52:19 PDT 2008
Committed by: kou
Update of /cvs/cairo/rcairo/src
In directory kemper:/tmp/cvs-serv9707/src
Modified Files:
cairo.def rb_cairo.h rb_cairo_context.c rb_cairo_exception.c
rb_cairo_font_face.c rb_cairo_private.c rb_cairo_private.h
rb_cairo_surface.c
Log Message:
* src/lib/cairo.rb (Cairo.exit_application): add.
* src/rb_cairo_surface.c: use rb_cairo__invoke_callback().
* src/rb_cairo_private.c, src/rb_cairo_private.h
(rb_cairo__invoke_callback): use rb_protect() and exit if an
exception is raised in callback.
* src/rb_cairo_font_face.c: support Cairo::UserFontFace.
* src/rb_cairo_exception.c, src/rb_cairo_private.h
(rb_cairo__exception_to_status): add.
* src/rb_cairo_context.c (cr_show_text_glyphs): initialize variables.
* src/cairo.def, src/rb_cairo.h: add
rb_cCairo_UserFontFace_TextToGlyphsData.
* test/test_font_face.rb: add tests for user font.
Index: cairo.def
===================================================================
RCS file: /cvs/cairo/rcairo/src/cairo.def,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- cairo.def 16 Aug 2008 08:16:37 -0000 1.16
+++ cairo.def 16 Aug 2008 12:52:16 -0000 1.17
@@ -18,6 +18,7 @@
rb_cCairo_FontFace DATA
rb_cCairo_ToyFontFace DATA
rb_cCairo_UserFontFace DATA
+ rb_cCairo_UserFontFace_TextToGlyphsData DATA
rb_cCairo_FontExtents DATA
rb_cCairo_FontOptions DATA
rb_cCairo_ScaledFont DATA
Index: rb_cairo.h
===================================================================
RCS file: /cvs/cairo/rcairo/src/rb_cairo.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- rb_cairo.h 16 Aug 2008 08:16:39 -0000 1.21
+++ rb_cairo.h 16 Aug 2008 12:52:16 -0000 1.22
@@ -86,6 +86,7 @@
RB_CAIRO_VAR VALUE rb_cCairo_FontFace;
RB_CAIRO_VAR VALUE rb_cCairo_ToyFontFace;
RB_CAIRO_VAR VALUE rb_cCairo_UserFontFace;
+RB_CAIRO_VAR VALUE rb_cCairo_UserFontFace_TextToGlyphsData;
RB_CAIRO_VAR VALUE rb_cCairo_FontExtents;
RB_CAIRO_VAR VALUE rb_cCairo_FontOptions;
RB_CAIRO_VAR VALUE rb_cCairo_ScaledFont;
Index: rb_cairo_context.c
===================================================================
RCS file: /cvs/cairo/rcairo/src/rb_cairo_context.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- rb_cairo_context.c 16 Aug 2008 08:34:18 -0000 1.27
+++ rb_cairo_context.c 16 Aug 2008 12:52:16 -0000 1.28
@@ -1185,10 +1185,10 @@
cairo_t *cr;
const char *utf8;
int utf8_len;
- cairo_glyph_t *glyphs;
- int num_glyphs;
- cairo_text_cluster_t *clusters;
- int num_clusters;
+ cairo_glyph_t *glyphs = NULL;
+ int num_glyphs = 0;
+ cairo_text_cluster_t *clusters = NULL;
+ int num_clusters = 0;
cairo_bool_t backward;
cr = _SELF;
@@ -1202,8 +1202,10 @@
glyphs, num_glyphs,
clusters, num_clusters,
backward);
- cairo_glyph_free (glyphs);
- cairo_text_cluster_free (clusters);
+ if (glyphs)
+ cairo_glyph_free (glyphs);
+ if (clusters)
+ cairo_text_cluster_free (clusters);
return self;
}
Index: rb_cairo_exception.c
===================================================================
RCS file: /cvs/cairo/rcairo/src/rb_cairo_exception.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- rb_cairo_exception.c 13 Aug 2008 08:27:44 -0000 1.3
+++ rb_cairo_exception.c 16 Aug 2008 12:52:16 -0000 1.4
@@ -13,6 +13,7 @@
*/
#include "rb_cairo.h"
+#include "rb_cairo_private.h"
static VALUE rb_eCairo_InvalidRestoreError;
static VALUE rb_eCairo_InvalidPopGroupError;
@@ -162,6 +163,83 @@
}
}
+cairo_status_t
+rb_cairo__exception_to_status (VALUE exception)
+{
+ if (NIL_P (exception))
+ return CAIRO_STATUS_SUCCESS;
+ else if (rb_cairo__is_kind_of (exception, rb_eNoMemError))
+ return CAIRO_STATUS_NO_MEMORY;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidRestoreError))
+ return CAIRO_STATUS_INVALID_RESTORE;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidPopGroupError))
+ return CAIRO_STATUS_INVALID_POP_GROUP;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_NoCurrentPointError))
+ return CAIRO_STATUS_NO_CURRENT_POINT;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidMatrixError))
+ return CAIRO_STATUS_INVALID_MATRIX;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidStatusError))
+ return CAIRO_STATUS_INVALID_STATUS;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_NullPointerError))
+ return CAIRO_STATUS_NULL_POINTER;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidStringError))
+ return CAIRO_STATUS_INVALID_STRING;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidPathDataError))
+ return CAIRO_STATUS_INVALID_PATH_DATA;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_ReadError))
+ return CAIRO_STATUS_READ_ERROR;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_WriteError))
+ return CAIRO_STATUS_WRITE_ERROR;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_SurfaceFinishedError))
+ return CAIRO_STATUS_SURFACE_FINISHED;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_SurfaceTypeMismatchError))
+ return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_PatternTypeMismatchError))
+ return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidContentError))
+ return CAIRO_STATUS_INVALID_CONTENT;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidFormatError))
+ return CAIRO_STATUS_INVALID_FORMAT;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidVisualError))
+ return CAIRO_STATUS_INVALID_VISUAL;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_FileNotFoundError))
+ return CAIRO_STATUS_FILE_NOT_FOUND;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidDashError))
+ return CAIRO_STATUS_INVALID_DASH;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidDscCommentError))
+ return CAIRO_STATUS_INVALID_DSC_COMMENT;
+#if CAIRO_CHECK_VERSION(1, 3, 0)
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidIndexError))
+ return CAIRO_STATUS_INVALID_INDEX;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_ClipNotRepresentableError))
+ return CAIRO_STATUS_CLIP_NOT_REPRESENTABLE;
+#endif
+#if CAIRO_CHECK_VERSION(1, 5, 6)
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_TempFileError))
+ return CAIRO_STATUS_TEMP_FILE_ERROR;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidStringError))
+ return CAIRO_STATUS_INVALID_STRIDE;
+#endif
+#if CAIRO_CHECK_VERSION(1, 7, 2)
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_FontTypeMismatch))
+ return CAIRO_STATUS_FONT_TYPE_MISMATCH;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_UserFontImmutable))
+ return CAIRO_STATUS_USER_FONT_IMMUTABLE;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_UserFontError))
+ return CAIRO_STATUS_USER_FONT_ERROR;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_NegativeCount))
+ return CAIRO_STATUS_NEGATIVE_COUNT;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidClusters))
+ return CAIRO_STATUS_INVALID_CLUSTERS;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidSlant))
+ return CAIRO_STATUS_INVALID_SLANT;
+ else if (rb_cairo__is_kind_of (exception, rb_eCairo_InvalidWeight))
+ return CAIRO_STATUS_INVALID_WEIGHT;
+#endif
+
+ return -1;
+}
+
void
Init_cairo_exception ()
{
Index: rb_cairo_font_face.c
===================================================================
RCS file: /cvs/cairo/rcairo/src/rb_cairo_font_face.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- rb_cairo_font_face.c 14 Aug 2008 08:11:12 -0000 1.5
+++ rb_cairo_font_face.c 16 Aug 2008 12:52:16 -0000 1.6
@@ -19,6 +19,24 @@
VALUE rb_cCairo_FontFace;
VALUE rb_cCairo_ToyFontFace = Qnil;
VALUE rb_cCairo_UserFontFace = Qnil;
+VALUE rb_cCairo_UserFontFace_TextToGlyphsData = Qnil;
+
+#if CAIRO_CHECK_VERSION(1, 7, 2)
+static cairo_user_data_key_t ruby_object_key;
+static ID cr_id_call;
+static ID cr_id_new;
+
+static ID cr_id_init;
+static ID cr_id_render_glyph;
+static ID cr_id_text_to_glyphs;
+static ID cr_id_unicode_to_glyph;
+
+static ID cr_id_at_glyphs;
+static ID cr_id_at_clusters;
+static ID cr_id_at_backward;
+static ID cr_id_at_need_glyphs;
+static ID cr_id_at_need_clusters;
+#endif
#define _SELF (RVAL2CRFONTFACE(self))
@@ -65,12 +83,14 @@
switch (cairo_font_face_get_type (face))
{
+#if CAIRO_CHECK_VERSION(1, 7, 2)
case CAIRO_FONT_TYPE_TOY:
klass = rb_cCairo_ToyFontFace;
break;
case CAIRO_FONT_TYPE_USER:
klass = rb_cCairo_UserFontFace;
break;
+#endif
default:
klass = rb_cCairo_FontFace;
break;
@@ -90,6 +110,7 @@
return Data_Wrap_Struct (klass, NULL, cr_font_face_free, NULL);
}
+#if CAIRO_CHECK_VERSION(1, 7, 2)
static VALUE
cr_toy_font_face_initialize (int argc, VALUE *argv, VALUE self)
{
@@ -151,10 +172,452 @@
return INT2NUM (cairo_toy_font_face_get_weight (_SELF));
}
+typedef struct cr_user_font_face_invoke_data
+{
+ VALUE receiver;
+ ID method;
+ int argc;
+ VALUE *argv;
+ cairo_status_t *status;
+ VALUE result;
+ cr_callback_func_t after_hook;
+ void *after_hook_data;
+} cr_user_font_face_invoke_data_t;
+
+static VALUE
+cr_user_font_face_invoke_body (VALUE user_data)
+{
+ cr_user_font_face_invoke_data_t *data;
+ VALUE result;
+
+ data = (cr_user_font_face_invoke_data_t *)user_data;
+ result = rb_funcall2 (data->receiver, data->method, data->argc, data->argv);
+ data->result = result;
+ if (data->after_hook)
+ result = data->after_hook(user_data);
+ return result;
+}
+
+static VALUE
+cr_user_font_face_invoke_rescue (VALUE user_data, VALUE exception)
+{
+ cr_user_font_face_invoke_data_t *data;
+
+ data = (cr_user_font_face_invoke_data_t *)user_data;
+ *(data->status) = rb_cairo__exception_to_status (exception);
+
+ if (*(data->status) == -1)
+ rb_exc_raise (exception);
+
+ return Qnil;
+}
+
+static VALUE
+cr_user_font_face_invoke_func (VALUE user_data)
+{
+ return rb_rescue2 (cr_user_font_face_invoke_body, user_data,
+ cr_user_font_face_invoke_rescue, user_data, rb_eException,
+ (VALUE)0);
+}
+
+static VALUE
+cr_user_font_face_init_func_after (VALUE user_data)
+{
+ cr_user_font_face_invoke_data_t *data;
+ cairo_font_extents_t *extents;
+
+ data = (cr_user_font_face_invoke_data_t *)user_data;
+ extents = data->after_hook_data;
+
+ *extents = *(RVAL2CRFONTEXTENTS (data->argv[2]));
+
+ return data->result;
+}
+
+static cairo_status_t
+cr_user_font_face_init_func (cairo_scaled_font_t *scaled_font,
+ cairo_t *cr, cairo_font_extents_t *extents)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_font_face_t *face;
+ VALUE self;
+ VALUE receiver = Qnil;
+ ID id_method_name = cr_id_call;
+
+ face = cairo_scaled_font_get_font_face (scaled_font);
+ self = (VALUE)cairo_font_face_get_user_data (face, &ruby_object_key);
+ receiver = rb_ivar_get (self, cr_id_init);
+ if (NIL_P (receiver) && rb_obj_respond_to (self, cr_id_init, Qtrue))
+ {
+ receiver = self;
+ id_method_name = cr_id_init;
+ }
+
+ if (!NIL_P (receiver))
+ {
+ cr_user_font_face_invoke_data_t data;
+ VALUE argv[3];
+
+ argv[0] = CRSCALEDFONT2RVAL (scaled_font);
+ argv[1] = CRCONTEXT2RVAL (cr);
+ argv[2] = CRFONTEXTENTS2RVAL (extents);
+
+ data.receiver = receiver;
+ data.method = id_method_name;
+ data.argc = 3;
+ data.argv = argv;
+ data.status = &status;
+ data.after_hook = cr_user_font_face_init_func_after;
+ data.after_hook_data = extents;
+
+ rb_cairo__invoke_callback (cr_user_font_face_invoke_func, (VALUE)&data);
+ }
+
+ return status;
+}
+
+static VALUE
+cr_user_font_face_render_glyph_func_after (VALUE user_data)
+{
+ cr_user_font_face_invoke_data_t *data;
+ cairo_text_extents_t *extents;
+
+ data = (cr_user_font_face_invoke_data_t *)user_data;
+ extents = data->after_hook_data;
+
+ *extents = *(RVAL2CRTEXTEXTENTS (data->argv[3]));
+
+ return data->result;
+}
+
+static cairo_status_t
+cr_user_font_face_render_glyph_func (cairo_scaled_font_t *scaled_font,
+ unsigned long glyph,
+ cairo_t *cr,
+ cairo_text_extents_t *extents)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_font_face_t *face;
+ VALUE self;
+ VALUE receiver = Qnil;
+ ID id_method_name = cr_id_call;
+
+ face = cairo_scaled_font_get_font_face (scaled_font);
+ self = (VALUE)cairo_font_face_get_user_data (face, &ruby_object_key);
+ receiver = rb_ivar_get (self, cr_id_render_glyph);
+ if (NIL_P (receiver) && rb_obj_respond_to (self, cr_id_render_glyph, Qtrue))
+ {
+ receiver = self;
+ id_method_name = cr_id_render_glyph;
+ }
+
+ if (!NIL_P (receiver))
+ {
+ cr_user_font_face_invoke_data_t data;
+ VALUE argv[4];
+
+ argv[0] = CRSCALEDFONT2RVAL (scaled_font);
+ argv[1] = ULONG2NUM (glyph);
+ argv[2] = CRCONTEXT2RVAL (cr);
+ argv[3] = CRTEXTEXTENTS2RVAL (extents);
+
+ data.receiver = receiver;
+ data.method = id_method_name;
+ data.argc = 4;
+ data.argv = argv;
+ data.status = &status;
+ data.after_hook = cr_user_font_face_render_glyph_func_after;
+ data.after_hook_data = extents;
+
+ rb_cairo__invoke_callback (cr_user_font_face_invoke_func, (VALUE)&data);
+ }
+
+ return status;
+}
+
+typedef struct _cr_text_to_glyphs_after_hook_data {
+ VALUE text_to_glyphs_data;
+ cairo_glyph_t **glyphs;
+ int *num_glyphs;
+ cairo_text_cluster_t **clusters;
+ int *num_clusters;
+ cairo_bool_t *backward;
+} cr_text_to_glyphs_after_hook_data_t;
+
+static VALUE
+cr_user_font_face_text_to_glyphs_func_after (VALUE user_data)
+{
+ cr_user_font_face_invoke_data_t *data;
+ cr_text_to_glyphs_after_hook_data_t *after_hook_data;
+ VALUE text_to_glyphs_data;
+
+
+ data = (cr_user_font_face_invoke_data_t *)user_data;
+ after_hook_data = data->after_hook_data;
+ text_to_glyphs_data = after_hook_data->text_to_glyphs_data;
+
+ if (after_hook_data->glyphs)
+ {
+ VALUE rb_glyphs;
+
+ rb_glyphs = rb_ivar_get (text_to_glyphs_data, cr_id_at_glyphs);
+ rb_cairo__glyphs_from_ruby_object (rb_glyphs,
+ after_hook_data->glyphs,
+ after_hook_data->num_glyphs);
+ }
+
+ if (after_hook_data->clusters)
+ {
+ VALUE rb_clusters;
+
+ rb_clusters = rb_ivar_get (text_to_glyphs_data, cr_id_at_clusters);
+ rb_cairo__text_clusters_from_ruby_object (rb_clusters,
+ after_hook_data->clusters,
+ after_hook_data->num_clusters);
+ }
+
+ if (after_hook_data->backward)
+ {
+ VALUE rb_backward;
+
+ rb_backward = rb_ivar_get (text_to_glyphs_data, cr_id_at_backward);
+ *(after_hook_data->backward) = RVAL2CBOOL (rb_backward);
+ }
+
+ return data->result;
+}
+
+static cairo_status_t
+cr_user_font_face_text_to_glyphs_func (cairo_scaled_font_t *scaled_font,
+ const char *utf8, int utf8_len,
+ cairo_glyph_t **glyphs, int *num_glyphs,
+ cairo_text_cluster_t **clusters,
+ int *num_clusters,
+ cairo_bool_t *backward)
+{
+ cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+ cairo_font_face_t *face;
+ VALUE self;
+ VALUE receiver = Qnil;
+ ID id_method_name = cr_id_call;
+
+ face = cairo_scaled_font_get_font_face (scaled_font);
+ self = (VALUE)cairo_font_face_get_user_data (face, &ruby_object_key);
+ receiver = rb_ivar_get (self, cr_id_text_to_glyphs);
+ if (NIL_P (receiver) && rb_obj_respond_to (self, cr_id_text_to_glyphs, Qtrue))
+ {
+ receiver = self;
+ id_method_name = cr_id_text_to_glyphs;
+ }
+
+ if (!NIL_P (receiver))
+ {
+ cr_user_font_face_invoke_data_t data;
+ cr_text_to_glyphs_after_hook_data_t after_hook_data;
+ VALUE text_to_glyphs_data;
+ VALUE argv[3];
+
+ argv[0] = CRSCALEDFONT2RVAL (scaled_font);
+ argv[1] = rb_str_new (utf8, utf8_len);
+ text_to_glyphs_data = rb_funcall (rb_cCairo_UserFontFace_TextToGlyphsData,
+ cr_id_new,
+ 2,
+ CBOOL2RVAL (glyphs != NULL),
+ CBOOL2RVAL (clusters != NULL));
+ argv[2] = text_to_glyphs_data;
+
+ data.receiver = receiver;
+ data.method = id_method_name;
+ data.argc = 3;
+ data.argv = argv;
+ data.status = &status;
+ data.after_hook = cr_user_font_face_text_to_glyphs_func_after;
+ data.after_hook_data = &after_hook_data;
+
+ after_hook_data.text_to_glyphs_data = text_to_glyphs_data;
+ after_hook_data.glyphs = glyphs;
+ after_hook_data.num_glyphs = num_glyphs;
+ after_hook_data.clusters = clusters;
+ after_hook_data.num_clusters = num_clusters;
+ after_hook_data.backward = backward;
+
+ rb_cairo__invoke_callback (cr_user_font_face_invoke_func, (VALUE)&data);
+ }
+
+ return status;
+}
+
+static VALUE
+cr_user_font_face_unicode_to_glyph_func_after (VALUE user_data)
+{
+ cr_user_font_face_invoke_data_t *data;
+ unsigned long *glyph_index;
+
+ data = (cr_user_font_face_invoke_data_t *)user_data;
+ glyph_index = data->after_hook_data;
+
+ *glyph_index = NUM2ULONG (data->result);
+
+ return data->result;
+}
+
+static cairo_status_t
+cr_user_font_face_unicode_to_glyph_func (cairo_scaled_font_t *scaled_font,
+ unsigned long unicode,
+ unsigned long *glyph_index)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_font_face_t *face;
+ VALUE self;
+ VALUE receiver = Qnil;
+ ID id_method_name = cr_id_call;
+
+ face = cairo_scaled_font_get_font_face (scaled_font);
+ self = (VALUE)cairo_font_face_get_user_data (face, &ruby_object_key);
+ receiver = rb_ivar_get (self, cr_id_unicode_to_glyph);
+ if (NIL_P (receiver) &&
+ rb_obj_respond_to (self, cr_id_unicode_to_glyph, Qtrue))
+ {
+ receiver = self;
+ id_method_name = cr_id_unicode_to_glyph;
+ }
+
+ if (NIL_P (receiver))
+ {
+ *glyph_index = unicode;
+ }
+ else
+ {
+ cr_user_font_face_invoke_data_t data;
+ VALUE argv[2];
+
+ argv[0] = CRSCALEDFONT2RVAL (scaled_font);
+ argv[1] = ULONG2NUM (unicode);
+
+ data.receiver = receiver;
+ data.method = id_method_name;
+ data.argc = 2;
+ data.argv = argv;
+ data.status = &status;
+ data.after_hook = cr_user_font_face_unicode_to_glyph_func_after;
+ data.after_hook_data = glyph_index;
+
+ rb_cairo__invoke_callback (cr_user_font_face_invoke_func, (VALUE)&data);
+ }
+
+ return status;
+}
+
+
+static VALUE
+cr_user_font_face_initialize (VALUE self)
+{
+ cairo_font_face_t *face;
+
+ face = cairo_user_font_face_create ();
+ cr_font_face_check_status (face);
+
+ cairo_font_face_set_user_data (face, &ruby_object_key, (void *)self, NULL);
+
+ cairo_user_font_face_set_init_func
+ (face, cr_user_font_face_init_func);
+ cairo_user_font_face_set_render_glyph_func
+ (face, cr_user_font_face_render_glyph_func);
+ cairo_user_font_face_set_text_to_glyphs_func
+ (face, cr_user_font_face_text_to_glyphs_func);
+ cairo_user_font_face_set_unicode_to_glyph_func
+ (face, cr_user_font_face_unicode_to_glyph_func);
+
+ rb_ivar_set (self, cr_id_init, Qnil);
+ rb_ivar_set (self, cr_id_render_glyph, Qnil);
+ rb_ivar_set (self, cr_id_text_to_glyphs, Qnil);
+ rb_ivar_set (self, cr_id_unicode_to_glyph, Qnil);
+
+ DATA_PTR (self) = face;
+
+ return Qnil;
+}
+
+static VALUE
+cr_user_font_face_on_init (VALUE self)
+{
+ rb_ivar_set (self, cr_id_init, rb_block_proc ());
+ return self;
+}
+
+static VALUE
+cr_user_font_face_on_render_glyph (VALUE self)
+{
+ rb_ivar_set (self, cr_id_render_glyph, rb_block_proc ());
+ return self;
+}
+
+static VALUE
+cr_user_font_face_on_text_to_glyphs (VALUE self)
+{
+ rb_ivar_set (self, cr_id_text_to_glyphs, rb_block_proc ());
+ return self;
+}
+
+static VALUE
+cr_user_font_face_on_unicode_to_glyph (VALUE self)
+{
+ rb_ivar_set (self, cr_id_unicode_to_glyph, rb_block_proc ());
+ return self;
+}
+
+
+static VALUE
+cr_text_to_glyphs_data_initialize (VALUE self,
+ VALUE need_glyphs, VALUE need_clusters)
+{
+ rb_ivar_set (self, cr_id_at_glyphs, Qnil);
+ rb_ivar_set (self, cr_id_at_clusters, Qnil);
+ rb_ivar_set (self, cr_id_at_backward, Qfalse);
+ rb_ivar_set (self, cr_id_at_need_glyphs, need_glyphs);
+ rb_ivar_set (self, cr_id_at_need_clusters, need_clusters);
+
+ return Qnil;
+}
+
+static VALUE
+cr_text_to_glyphs_data_backward_p (VALUE self)
+{
+ return rb_ivar_get (self, cr_id_at_backward);
+}
+
+static VALUE
+cr_text_to_glyphs_data_need_glyphs (VALUE self)
+{
+ return rb_ivar_get (self, cr_id_at_need_glyphs);
+}
+
+static VALUE
+cr_text_to_glyphs_data_need_clusters (VALUE self)
+{
+ return rb_ivar_get (self, cr_id_at_need_clusters);
+}
+#endif
void
Init_cairo_font (void)
{
+#if CAIRO_CHECK_VERSION(1, 7, 2)
+ cr_id_call = rb_intern ("call");
+ cr_id_new = rb_intern ("new");
+
+ cr_id_init = rb_intern ("init");
+ cr_id_render_glyph = rb_intern ("render_glyph");
+ cr_id_text_to_glyphs = rb_intern ("text_to_glyphs");
+ cr_id_unicode_to_glyph = rb_intern ("unicode_to_glyph");
+
+ cr_id_at_glyphs = rb_intern ("@glyphs");
+ cr_id_at_clusters = rb_intern ("@clusters");
+ cr_id_at_backward = rb_intern ("@backward");
+ cr_id_at_need_glyphs = rb_intern ("@need_glyphs");
+ cr_id_at_need_clusters = rb_intern ("@need_clusters");
+#endif
+
rb_cCairo_FontFace =
rb_define_class_under (rb_mCairo, "FontFace", rb_cObject);
rb_define_alloc_func (rb_cCairo_FontFace, cr_font_face_allocate);
@@ -173,7 +636,41 @@
rb_define_method (rb_cCairo_ToyFontFace, "weight",
cr_toy_font_face_get_weight, 0);
+
rb_cCairo_UserFontFace =
rb_define_class_under (rb_mCairo, "UserFontFace", rb_cCairo_FontFace);
+
+ rb_define_method (rb_cCairo_UserFontFace, "initialize",
+ cr_user_font_face_initialize, 0);
+
+ rb_define_method (rb_cCairo_UserFontFace, "on_init",
+ cr_user_font_face_on_init, 0);
+ rb_define_method (rb_cCairo_UserFontFace, "on_render_glyph",
+ cr_user_font_face_on_render_glyph, 0);
+ rb_define_method (rb_cCairo_UserFontFace, "on_text_to_glyphs",
+ cr_user_font_face_on_text_to_glyphs, 0);
+ rb_define_method (rb_cCairo_UserFontFace, "on_unicode_to_glyph",
+ cr_user_font_face_on_unicode_to_glyph, 0);
+
+
+ rb_cCairo_UserFontFace_TextToGlyphsData =
+ rb_define_class_under (rb_cCairo_UserFontFace,
+ "TextToGlyphsData", rb_cObject);
+ rb_attr (rb_cCairo_UserFontFace_TextToGlyphsData, rb_intern ("glyphs"),
+ CR_TRUE, CR_TRUE, CR_TRUE);
+ rb_attr (rb_cCairo_UserFontFace_TextToGlyphsData, rb_intern ("clusters"),
+ CR_TRUE, CR_TRUE, CR_TRUE);
+ rb_attr (rb_cCairo_UserFontFace_TextToGlyphsData, rb_intern ("backward"),
+ CR_FALSE, CR_TRUE, CR_TRUE);
+
+ rb_define_method (rb_cCairo_UserFontFace_TextToGlyphsData,
+ "initialize", cr_text_to_glyphs_data_initialize, 2);
+
+ rb_define_method (rb_cCairo_UserFontFace_TextToGlyphsData,
+ "backward?", cr_text_to_glyphs_data_backward_p, 0);
+ rb_define_method (rb_cCairo_UserFontFace_TextToGlyphsData,
+ "need_glyphs?", cr_text_to_glyphs_data_need_glyphs, 0);
+ rb_define_method (rb_cCairo_UserFontFace_TextToGlyphsData,
+ "need_clusters?", cr_text_to_glyphs_data_need_clusters, 0);
#endif
}
Index: rb_cairo_private.c
===================================================================
RCS file: /cvs/cairo/rcairo/src/rb_cairo_private.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- rb_cairo_private.c 16 Aug 2008 08:34:18 -0000 1.8
+++ rb_cairo_private.c 16 Aug 2008 12:52:16 -0000 1.9
@@ -18,6 +18,7 @@
static ID cr_id_objects;
static ID cr_id_dup;
static ID cr_id_inspect;
+static ID cr_id_exit_application;
VALUE
rb_cairo__float_array (double *values, unsigned count)
@@ -148,11 +149,19 @@
rb_cairo__glyphs_from_ruby_object (VALUE rb_glyphs,
cairo_glyph_t **glyphs, int *num_glyphs)
{
- int i;
+ int i, len;
- *num_glyphs = RARRAY_LEN (rb_glyphs);
- *glyphs = cairo_glyph_allocate (*num_glyphs);
- for (i = 0; i < *num_glyphs; i++)
+ if (NIL_P (rb_glyphs))
+ {
+ *num_glyphs = 0;
+ return;
+ }
+
+ len = RARRAY_LEN (rb_glyphs);
+ if (*num_glyphs < len)
+ *glyphs = cairo_glyph_allocate (len);
+ *num_glyphs = len;
+ for (i = 0; i < len; i++)
{
cairo_glyph_t *glyph;
@@ -182,11 +191,19 @@
cairo_text_cluster_t **clusters,
int *num_clusters)
{
- int i;
+ int i, len;
- *num_clusters = RARRAY_LEN (rb_clusters);
- *clusters = cairo_text_cluster_allocate (*num_clusters);
- for (i = 0; i < *num_clusters; i++)
+ if (NIL_P (rb_clusters))
+ {
+ *num_clusters = 0;
+ return;
+ }
+
+ len = RARRAY_LEN (rb_clusters);
+ if (*num_clusters < len)
+ *clusters = cairo_text_cluster_allocate (len);
+ *num_clusters = len;
+ for (i = 0; i < len; i++)
{
cairo_text_cluster_t *cluster;
@@ -195,6 +212,23 @@
}
}
+VALUE
+rb_cairo__invoke_callback (cr_callback_func_t func, VALUE data)
+{
+ int state = 0;
+ VALUE result, exception;
+
+ result = rb_protect (func, data, &state);
+ if (state)
+ {
+ exception = RB_ERRINFO;
+ if (exception)
+ rb_funcall (rb_mCairo, cr_id_exit_application, 2,
+ exception, INT2NUM (EXIT_FAILURE));
+ }
+ return result;
+}
+
void
Init_cairo_private (void)
{
@@ -202,4 +236,5 @@
cr_id_objects = rb_intern ("objects");
cr_id_dup = rb_intern ("dup");
cr_id_inspect = rb_intern ("inspect");
+ cr_id_exit_application = rb_intern ("exit_application");
}
Index: rb_cairo_private.h
===================================================================
RCS file: /cvs/cairo/rcairo/src/rb_cairo_private.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- rb_cairo_private.h 16 Aug 2008 08:34:18 -0000 1.11
+++ rb_cairo_private.h 16 Aug 2008 12:52:17 -0000 1.12
@@ -17,6 +17,8 @@
#define CR_TRUE 1
#define CR_FALSE 0
+#define CAIRO_INT_STATUS_UNSUPPORTED 100
+
#define CSTR2RVAL(str) rb_str_new2(str)
#define RVAL2CSTR(str) StringValueCStr(str)
@@ -102,4 +104,9 @@
cairo_text_cluster_t **clusters,
int *num_clusters);
+cairo_status_t rb_cairo__exception_to_status (VALUE exception);
+
+typedef VALUE (*cr_callback_func_t) (VALUE user_data);
+VALUE rb_cairo__invoke_callback (cr_callback_func_t func, VALUE user_data);
+
#endif
Index: rb_cairo_surface.c
===================================================================
RCS file: /cvs/cairo/rcairo/src/rb_cairo_surface.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- rb_cairo_surface.c 14 Aug 2008 08:21:57 -0000 1.40
+++ rb_cairo_surface.c 16 Aug 2008 12:52:17 -0000 1.41
@@ -159,6 +159,11 @@
unsigned int length;
} cr_io_callback_closure_t;
+typedef struct cr_invoke_data {
+ cr_callback_func_t func;
+ VALUE data;
+} cr_invoke_data_t;
+
#if HAS_CREATE_CR_CLOSURE_SURFACE
static cr_io_callback_closure_t *
cr_closure_new (VALUE target)
@@ -194,6 +199,17 @@
return Qnil;
}
+static VALUE
+cr_surface_invoke_io_func (VALUE user_data)
+{
+ cr_invoke_data_t *data;
+
+ data = (cr_invoke_data_t *)user_data;
+ return rb_rescue2 (data->func, data->data,
+ cr_surface_io_func_rescue, data->data, rb_eException,
+ (VALUE)0);
+}
+
/* write callback */
static VALUE
cr_surface_write_func_invoke (VALUE write_closure)
@@ -226,15 +242,16 @@
const unsigned char *data, unsigned int length)
{
cr_io_callback_closure_t *closure;
+ cr_invoke_data_t invoke_data;
closure = (cr_io_callback_closure_t *)write_closure;
closure->data = (unsigned char *)data;
closure->length = length;
-
- rb_rescue2 (cr_surface_write_func_invoke, (VALUE) closure,
- cr_surface_io_func_rescue, (VALUE) closure, rb_eException,
- (VALUE)0);
-
+
+ invoke_data.func = cr_surface_write_func_invoke;
+ invoke_data.data = (VALUE)closure;
+ rb_cairo__invoke_callback (cr_surface_invoke_io_func, (VALUE)&invoke_data);
+
if (NIL_P (closure->error))
return CAIRO_STATUS_SUCCESS;
else
@@ -270,14 +287,16 @@
unsigned char *data, unsigned int length)
{
cr_io_callback_closure_t *closure;
+ cr_invoke_data_t invoke_data;
closure = (cr_io_callback_closure_t *)read_closure;
closure->data = data;
closure->length = length;
- rb_rescue2 (cr_surface_read_func_invoke, (VALUE) closure,
- cr_surface_io_func_rescue, (VALUE) closure, rb_eException,
- (VALUE)0);
-
+
+ invoke_data.func = cr_surface_read_func_invoke;
+ invoke_data.data = (VALUE)closure;
+ rb_cairo__invoke_callback (cr_surface_invoke_io_func, (VALUE)&invoke_data);
+
if (NIL_P (closure->error))
return CAIRO_STATUS_SUCCESS;
else
More information about the cairo-commit
mailing list