# This module provides an interface to the top level bits of libvips # via ruby-ffi. # # Author:: John Cupitt (mailto:jcupitt@gmail.com) # License:: MIT require 'ffi' module Vips private # debugging support attach_function :vips_object_print_all, [], :void # we must init these by hand, since they are usually made on first image # create attach_function :vips_band_format_get_type, [], :GType attach_function :vips_interpretation_get_type, [], :GType attach_function :vips_coding_get_type, [], :GType public # some handy gtypes IMAGE_TYPE = GObject::g_type_from_name "VipsImage" ARRAY_INT_TYPE = GObject::g_type_from_name "VipsArrayInt" ARRAY_DOUBLE_TYPE = GObject::g_type_from_name "VipsArrayDouble" ARRAY_IMAGE_TYPE = GObject::g_type_from_name "VipsArrayImage" REFSTR_TYPE = GObject::g_type_from_name "VipsRefString" BLOB_TYPE = GObject::g_type_from_name "VipsBlob" BAND_FORMAT_TYPE = Vips::vips_band_format_get_type INTERPRETATION_TYPE = Vips::vips_interpretation_get_type CODING_TYPE = Vips::vips_coding_get_type private attach_function :vips_enum_from_nick, [:string, :GType, :string], :int attach_function :vips_enum_nick, [:GType, :int], :string attach_function :vips_value_set_ref_string, [GObject::GValue.ptr, :string], :void attach_function :vips_value_set_array_double, [GObject::GValue.ptr, :pointer, :int], :void attach_function :vips_value_set_array_int, [GObject::GValue.ptr, :pointer, :int], :void attach_function :vips_value_set_array_image, [GObject::GValue.ptr, :int], :void callback :free_fn, [:pointer], :void attach_function :vips_value_set_blob, [GObject::GValue.ptr, :free_fn, :pointer, :size_t], :void class SizeStruct < FFI::Struct layout :value, :size_t end class IntStruct < FFI::Struct layout :value, :int end attach_function :vips_value_get_ref_string, [GObject::GValue.ptr, SizeStruct.ptr], :string attach_function :vips_value_get_array_double, [GObject::GValue.ptr, IntStruct.ptr], :pointer attach_function :vips_value_get_array_int, [GObject::GValue.ptr, IntStruct.ptr], :pointer attach_function :vips_value_get_array_image, [GObject::GValue.ptr, IntStruct.ptr], :pointer attach_function :vips_value_get_blob, [GObject::GValue.ptr, SizeStruct.ptr], :pointer attach_function :type_find, :vips_type_find, [:string, :string], :GType class Object < GObject::GObject # print all active VipsObjects, with their reference counts. Handy for # debugging ruby-vips. def self.print_all GC.start Vips::vips_object_print_all end # the layout of the VipsObject struct module ObjectLayout def self.included base base.class_eval do # don't actually need most of these layout :parent, GObject::GObject::Struct, :constructed, :int, :static_object, :int, :argument_table, :pointer, :nickname, :string, :description, :string, :preclose, :int, :close, :int, :postclose, :int, :local_memory, :size_t end end end class Struct < GObject::GObject::Struct include ObjectLayout end class ManagedStruct < GObject::GObject::ManagedStruct include ObjectLayout end def get_typeof_property name pspec = GObject::GParamSpecPtr.new argument_class = Vips::ArgumentClassPtr.new argument_instance = Vips::ArgumentInstancePtr.new result = Vips::vips_object_get_argument self, name, pspec, argument_class, argument_instance return 0 if result != 0 pspec[:value][:value_type] end def get_typeof name get_typeof_property name end def get name gtype = get_typeof_property name gvalue = GObject::GValue.alloc gvalue.init gtype GObject::g_object_get_property self, name, gvalue result = gvalue.get GLib::logger.debug("Vips::Object.get") {"#{name} == #{result}"} return result end def set name, value GLib::logger.debug("Vips::Object.set") {"#{name} = #{value}"} gtype = get_typeof_property name gvalue = GObject::GValue.alloc gvalue.init gtype gvalue.set value GObject::g_object_set_property self, name, gvalue end end class ObjectClass < FFI::Struct # opaque end class Argument < FFI::Struct layout :pspec, GObject::GParamSpec.ptr end class ArgumentInstance < Argument layout :parent, Argument # rest opaque end # enum VipsArgumentFlags ARGUMENT_REQUIRED = 1 ARGUMENT_CONSTRUCT = 2 ARGUMENT_SET_ONCE = 4 ARGUMENT_SET_ALWAYS = 8 ARGUMENT_INPUT = 16 ARGUMENT_OUTPUT = 32 ARGUMENT_DEPRECATED = 64 ARGUMENT_MODIFY = 128 ARGUMENT_FLAGS = { :required => ARGUMENT_REQUIRED, :construct => ARGUMENT_CONSTRUCT, :set_once => ARGUMENT_SET_ONCE, :set_always => ARGUMENT_SET_ALWAYS, :input => ARGUMENT_INPUT, :output => ARGUMENT_OUTPUT, :deprecated => ARGUMENT_DEPRECATED, :modify => ARGUMENT_MODIFY } class ArgumentClass < Argument layout :parent, Argument, :object_class, ObjectClass.ptr, :flags, :uint, :priority, :int, :offset, :ulong_long end class ArgumentClassPtr < FFI::Struct layout :value, ArgumentClass.ptr end class ArgumentInstancePtr < FFI::Struct layout :value, ArgumentInstance.ptr end # just use :pointer, not VipsObject.ptr, to avoid casting gobject # subclasses attach_function :vips_object_get_argument, [:pointer, :string, GObject::GParamSpecPtr.ptr, ArgumentClassPtr.ptr, ArgumentInstancePtr.ptr], :int attach_function :vips_object_print_all, [], :void attach_function :vips_object_set_from_string, [:pointer, :string], :int callback :type_map_fn, [:GType, :pointer], :pointer attach_function :vips_type_map, [:GType, :type_map_fn, :pointer], :pointer attach_function :vips_object_get_description, [:pointer], :string end