/vendor/cache/ruby/2.7.0/gems/ruby-vips-2.0.17/lib/vips/gvalue.rb
Ruby | 287 lines | 168 code | 58 blank | 61 comment | 9 complexity | bfb9764cd8053268342794bebd14f9fb MD5 | raw file
- # This module provides an interface GValue via ruby-ffi.
- #
- # Author:: John Cupitt (mailto:jcupitt@gmail.com)
- # License:: MIT
- require 'ffi'
- module GObject
- # Represent a GValue. Example use:
- #
- # ```ruby
- # gvalue = GValue::alloc
- # gvalue.init GObject::GDOUBLE_TYPE
- # gvalue.set 3.1415
- # value = gvalue.get
- # # optional -- drop any ref the gvalue had
- # gvalue.unset
- # ```
- #
- # Lifetime is managed automatically. It doesn't know about all GType values,
- # but it does know the ones that libvips uses.
- class GValue < FFI::ManagedStruct
- layout :gtype, :GType,
- :data, [:ulong_long, 2]
- # convert an enum value (str/symb/int) into an int ready for libvips
- def self.from_nick(gtype, value)
- value = value.to_s if value.is_a? Symbol
- if value.is_a? String
- # libvips expects "-" as a separator in enum names, but "_" is more
- # convenient for ruby, eg. :b_w
- value = Vips::vips_enum_from_nick "ruby-vips", gtype, value.tr("_", "-")
- if value == -1
- raise Vips::Error
- end
- end
- value
- end
- # convert an int enum back into a symbol
- def self.to_nick(gtype, enum_value)
- enum_name = Vips::vips_enum_nick gtype, enum_value
- if enum_name == nil
- raise Vips::Error
- end
- enum_name.to_sym
- end
- def self.release ptr
- # GLib::logger.debug("GObject::GValue::release") {"ptr = #{ptr}"}
- ::GObject::g_value_unset ptr
- end
- # Allocate memory for a GValue and return a class wrapper. Memory will
- # be freed automatically when it goes out of scope. The GValue is inited
- # to 0, use {GValue.init} to set a type.
- #
- # @return [GValue] a new gvalue set to 0
- def self.alloc
- # allocate memory
- memory = FFI::MemoryPointer.new GValue
- # make this alloc autorelease ... we mustn't release in
- # GValue::release, since we are used to wrap GValue pointers
- # made by other people
- pointer = FFI::Pointer.new GValue, memory
- # ... and wrap in a GValue
- return GValue.new pointer
- end
- # Set the type of thing a gvalue can hold.
- #
- # @param gtype [GType] the type of thing this GValue can hold.
- def init gtype
- ::GObject::g_value_init self, gtype
- end
- # Set the value of a GValue. The value is converted to the type of the
- # GValue, if possible.
- #
- # @param value [Any] The value to set
- def set value
- # GLib::logger.debug("GObject::GValue.set") {
- # "value = #{value.inspect[0..50]}"
- # }
- gtype = self[:gtype]
- fundamental = ::GObject::g_type_fundamental gtype
- case gtype
- when GBOOL_TYPE
- ::GObject::g_value_set_boolean self, (value ? 1 : 0)
- when GINT_TYPE
- ::GObject::g_value_set_int self, value
- when GUINT64_TYPE
- ::GObject::g_value_set_uint64 self, value
- when GDOUBLE_TYPE
- ::GObject::g_value_set_double self, value
- when GSTR_TYPE
- ::GObject::g_value_set_string self, value
- when Vips::REFSTR_TYPE
- ::Vips::vips_value_set_ref_string self, value
- when Vips::ARRAY_INT_TYPE
- value = [value] unless value.is_a? Array
- Vips::vips_value_set_array_int self, nil, value.length
- ptr = Vips::vips_value_get_array_int self, nil
- ptr.write_array_of_int32 value
- when Vips::ARRAY_DOUBLE_TYPE
- value = [value] unless value.is_a? Array
- # this will allocate an array in the gvalue
- Vips::vips_value_set_array_double self, nil, value.length
- # pull the array out and fill it
- ptr = Vips::vips_value_get_array_double self, nil
- ptr.write_array_of_double value
- when Vips::ARRAY_IMAGE_TYPE
- value = [value] unless value.is_a? Array
- Vips::vips_value_set_array_image self, value.length
- ptr = Vips::vips_value_get_array_image self, nil
- ptr.write_array_of_pointer value
- # the gvalue needs a ref on each of the images
- value.each { |image| ::GObject::g_object_ref image }
- when Vips::BLOB_TYPE
- len = value.bytesize
- ptr = GLib::g_malloc len
- Vips::vips_value_set_blob self, GLib::G_FREE, ptr, len
- ptr.write_bytes value
- else
- case fundamental
- when GFLAGS_TYPE
- ::GObject::g_value_set_flags self, value
- when GENUM_TYPE
- enum_value = GValue.from_nick(self[:gtype], value)
- ::GObject::g_value_set_enum self, enum_value
- when GOBJECT_TYPE
- ::GObject::g_value_set_object self, value
- else
- raise Vips::Error, "unimplemented gtype for set: " +
- "#{::GObject::g_type_name gtype} (#{gtype})"
- end
- end
- end
- # Get the value of a GValue. The value is converted to a Ruby type in
- # the obvious way.
- #
- # @return [Any] the value held by the GValue
- def get
- gtype = self[:gtype]
- fundamental = ::GObject::g_type_fundamental gtype
- result = nil
- case gtype
- when GBOOL_TYPE
- result = ::GObject::g_value_get_boolean(self) != 0 ? true : false
- when GINT_TYPE
- result = ::GObject::g_value_get_int self
- when GUINT64_TYPE
- result = ::GObject::g_value_get_uint64 self
- when GDOUBLE_TYPE
- result = ::GObject::g_value_get_double self
- when GSTR_TYPE
- result = ::GObject::g_value_get_string self
- when Vips::REFSTR_TYPE
- len = Vips::SizeStruct.new
- result = ::Vips::vips_value_get_ref_string self, len
- when Vips::ARRAY_INT_TYPE
- len = Vips::IntStruct.new
- array = Vips::vips_value_get_array_int self, len
- result = array.get_array_of_int32 0, len[:value]
- when Vips::ARRAY_DOUBLE_TYPE
- len = Vips::IntStruct.new
- array = Vips::vips_value_get_array_double self, len
- result = array.get_array_of_double 0, len[:value]
- when Vips::ARRAY_IMAGE_TYPE
- len = Vips::IntStruct.new
- array = Vips::vips_value_get_array_image self, len
- result = array.get_array_of_pointer 0, len[:value]
- result.map! do |pointer|
- ::GObject::g_object_ref pointer
- Vips::Image.new pointer
- end
- when Vips::BLOB_TYPE
- len = Vips::SizeStruct.new
- array = Vips::vips_value_get_blob self, len
- result = array.get_bytes 0, len[:value]
- else
- case fundamental
- when GFLAGS_TYPE
- result = ::GObject::g_value_get_flags self
- when GENUM_TYPE
- enum_value = ::GObject::g_value_get_enum(self)
- result = GValue.to_nick self[:gtype], enum_value
- when GOBJECT_TYPE
- obj = ::GObject::g_value_get_object self
- # g_value_get_object() does not add a ref ... we need to add
- # one to match the unref in gobject release
- ::GObject::g_object_ref obj
- result = Vips::Image.new obj
- else
- raise Vips::Error, "unimplemented gtype for get: " +
- "#{::GObject::g_type_name gtype} (#{gtype})"
- end
- end
- # GLib::logger.debug("GObject::GValue.get") {
- # "result = #{result.inspect[0..50]}"
- # }
- return result
- end
- # Clear the thing held by a GValue.
- #
- # This happens automatically when a GValue is GCed, but this method can be
- # handy if you need to drop a reference explicitly for some reason.
- def unset
- ::GObject::g_value_unset self
- end
- end
- attach_function :g_value_init, [GValue.ptr, :GType], :void
- # we must use a plain :pointer here, since we call this from #release, which
- # just gives us the unwrapped pointer, not the ruby class
- attach_function :g_value_unset, [:pointer], :void
- attach_function :g_value_set_boolean, [GValue.ptr, :int], :void
- attach_function :g_value_set_int, [GValue.ptr, :int], :void
- attach_function :g_value_set_uint64, [GValue.ptr, :uint64], :void
- attach_function :g_value_set_double, [GValue.ptr, :double], :void
- attach_function :g_value_set_enum, [GValue.ptr, :int], :void
- attach_function :g_value_set_flags, [GValue.ptr, :uint], :void
- attach_function :g_value_set_string, [GValue.ptr, :string], :void
- attach_function :g_value_set_object, [GValue.ptr, :pointer], :void
- attach_function :g_value_get_boolean, [GValue.ptr], :int
- attach_function :g_value_get_int, [GValue.ptr], :int
- attach_function :g_value_get_uint64, [GValue.ptr], :uint64
- attach_function :g_value_get_double, [GValue.ptr], :double
- attach_function :g_value_get_enum, [GValue.ptr], :int
- attach_function :g_value_get_flags, [GValue.ptr], :int
- attach_function :g_value_get_string, [GValue.ptr], :string
- attach_function :g_value_get_object, [GValue.ptr], :pointer
- # use :pointer rather than GObject.ptr to avoid casting later
- attach_function :g_object_set_property,
- [:pointer, :string, GValue.ptr], :void
- attach_function :g_object_get_property,
- [:pointer, :string, GValue.ptr], :void
- end