/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */ /********************************************************************** rbart_affine.c - Art::Affine class of ruby $Author: ggc $ $Date: 2007/07/13 16:07:33 $ Copyright (C) 2004 Ruby-GNOME2 Project Team Copyright (C) 2002,2003 KUBO Takehiro **********************************************************************/ #include "rbart.h" VALUE artAffine; /* Below 2 macros are available only when obj is self or after * checking that obj is certainly a instance of Art::Affine. */ #define Affine_Ptr(obj) ((double *)(RDATA(obj)->data)) #define Affine_Set(obj, val) memcpy(Affine_Ptr(obj), val, sizeof(double[6])) /**********************************************************/ double * get_art_affine(obj) VALUE obj; { if (!rb_obj_is_instance_of(obj, artAffine)) rb_raise(rb_eTypeError, "not an ArtAffine"); return Affine_Ptr(obj); } VALUE make_art_affine(affine) double affine[6]; { double *ptr = xmalloc(sizeof(double[6])); memcpy(ptr, affine, sizeof(double[6])); return Data_Wrap_Struct(artAffine, 0, xfree, ptr); } /**********************************************************/ static VALUE affine_initialize(argc, argv, klass) int argc; VALUE *argv; VALUE klass; { int i; double* affine = xmalloc(sizeof(double[6])); if (argc == 1) { Check_Type(argv[0], T_ARRAY); if (RARRAY(argv[0])->len != 6) rb_raise(rb_eArgError, "wrong size of Array (expect 6)"); argv = RARRAY(argv[0])->ptr; } else if (argc != 6) { rb_raise(rb_eArgError, "wrong # of argument (expect an array(5 members) or 6 parameters)"); } for (i = 0;i < 6;i++) affine[i] = NUM2DBL(argv[i]); RDATA(klass)->data = affine; return Qnil; } static VALUE affine_s_identity(klass) VALUE klass; { double affine[6]; art_affine_identity(affine); return make_art_affine(affine); } static VALUE affine_s_scale(klass, sx, sy) VALUE klass, sx, sy; { double affine[6]; art_affine_scale(affine, NUM2DBL(sx), NUM2DBL(sy)); return make_art_affine(affine); } static VALUE affine_s_rotate(klass, theta) VALUE klass, theta; { double affine[6]; art_affine_rotate(affine, NUM2DBL(theta)); return make_art_affine(affine); } static VALUE affine_s_shear(klass, theta) VALUE klass, theta; { double affine[6]; art_affine_shear(affine, NUM2DBL(theta)); return make_art_affine(affine); } static VALUE affine_s_translate(klass, tx, ty) VALUE klass, tx, ty; { double affine[6]; art_affine_translate(affine, NUM2DBL(tx), NUM2DBL(ty)); return make_art_affine(affine); } static VALUE affine_point(argc, argv, self) int argc; VALUE *argv, self; { ArtPoint src; ArtPoint dst; if (argc == 1) { if (TYPE(argv[0]) != T_ARRAY) goto arg_error; if (RARRAY(argv[0])-> len != 2) goto arg_error; src.x = NUM2DBL(RARRAY(argv[0])->ptr[0]); src.y = NUM2DBL(RARRAY(argv[0])->ptr[1]); } else if (argc == 2) { src.x = NUM2DBL(argv[0]); src.y = NUM2DBL(argv[1]); } else { goto arg_error; } art_affine_point(&dst, &src, Affine_Ptr(self)); return rb_ary_new3(2, rb_float_new(dst.x), rb_float_new(dst.y)); arg_error: rb_raise(rb_eArgError, "wrong argument format (expect (x, y) or ([x, y]).)"); } static VALUE affine_invert(self) VALUE self; { double affine[6]; art_affine_invert(affine, Affine_Ptr(self)); return make_art_affine(affine); } static VALUE affine_invert_bang(self) VALUE self; { double affine[6]; art_affine_invert(affine, Affine_Ptr(self)); Affine_Set(self, affine); return self; } static VALUE affine_flip(self, horz, vert) VALUE self, horz, vert; { double affine[6]; art_affine_flip(affine, Affine_Ptr(self), RVAL2CBOOL(horz), RVAL2CBOOL(vert)); return make_art_affine(affine); } static VALUE affine_flip_bang(self, horz, vert) VALUE self, horz, vert; { double affine[6]; art_affine_flip(affine, Affine_Ptr(self), RVAL2CBOOL(horz), RVAL2CBOOL(vert)); Affine_Set(self, affine); return self; } static VALUE affine_to_s(self) VALUE self; { char str[255]; VALUE ret; double* affine = Affine_Ptr(self); if (affine) art_affine_to_string(str, affine); else str[0] = '\0'; ret = rb_str_new2("<"); rb_str_cat2(ret, rb_class2name(CLASS_OF(self))); if (str[0] != '\0') { rb_str_cat2(ret, ":"); rb_str_cat2(ret, str); } rb_str_cat2(ret, ">"); return ret; } static VALUE affine_to_a(self) VALUE self; { double *affine = Affine_Ptr(self); return rb_ary_new3(6, rb_float_new(affine[0]), rb_float_new(affine[1]), rb_float_new(affine[2]), rb_float_new(affine[3]), rb_float_new(affine[4]), rb_float_new(affine[5])); } static VALUE affine_expansion(self) VALUE self; { return rb_float_new(art_affine_expansion(Affine_Ptr(self))); } static VALUE affine_rectiliner(self) VALUE self; { return CBOOL2RVAL(art_affine_rectilinear(Affine_Ptr(self))); } static VALUE affine_multiply(self, right) VALUE self, right; { double affine[6]; art_affine_multiply(affine, get_art_affine(right), Affine_Ptr(self)); return make_art_affine(affine); } static VALUE affine_equal(self, right) VALUE self, right; { if (!rb_obj_is_instance_of(right, artAffine)) { return Qfalse; } return CBOOL2RVAL(art_affine_equal(Affine_Ptr(self), Affine_Ptr(right))); } void Init_art_affine(mArt) VALUE mArt; { artAffine = rb_define_class_under(mArt, "Affine", rb_cData); RBART_INIT_FUNC(artAffine); rb_define_singleton_method(artAffine, "identity", affine_s_identity, 0); rb_define_singleton_method(artAffine, "scale", affine_s_scale, 2); rb_define_singleton_method(artAffine, "rotate", affine_s_rotate, 1); rb_define_singleton_method(artAffine, "shear", affine_s_shear, 1); rb_define_singleton_method(artAffine, "translate", affine_s_translate, 2); rb_define_method(artAffine, "initialize", affine_initialize, -1); rb_define_method(artAffine, "point", affine_point, -1); rb_define_method(artAffine, "invert", affine_invert, 0); rb_define_method(artAffine, "invert!", affine_invert_bang, 0); rb_define_method(artAffine, "flip", affine_flip, 2); rb_define_method(artAffine, "flip!", affine_flip_bang, 2); rb_define_method(artAffine, "to_s", affine_to_s, 0); rb_define_method(artAffine, "to_a", affine_to_a, 0); rb_define_method(artAffine, "expansion", affine_expansion, 0); rb_define_method(artAffine, "rectiliner", affine_rectiliner, 0); rb_define_method(artAffine, "*", affine_multiply, 1); rb_define_method(artAffine, "==", affine_equal, 1); rb_define_alias(artAffine, "inverse", "invert"); rb_define_alias(artAffine, "inverse!", "invert!"); rb_define_alias(artAffine, "call", "point"); rb_define_alias(artAffine, "[]", "point"); rb_define_alias(artAffine, "act", "point"); }