PageRenderTime 409ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/cache/ruby/2.7.0/gems/ruby-vips-2.0.17/lib/vips/gvalue.rb

https://gitlab.com/gitnyasha/zimcreative
Ruby | 287 lines | 168 code | 58 blank | 61 comment | 9 complexity | bfb9764cd8053268342794bebd14f9fb MD5 | raw file
  1. # This module provides an interface GValue via ruby-ffi.
  2. #
  3. # Author:: John Cupitt (mailto:jcupitt@gmail.com)
  4. # License:: MIT
  5. require 'ffi'
  6. module GObject
  7. # Represent a GValue. Example use:
  8. #
  9. # ```ruby
  10. # gvalue = GValue::alloc
  11. # gvalue.init GObject::GDOUBLE_TYPE
  12. # gvalue.set 3.1415
  13. # value = gvalue.get
  14. # # optional -- drop any ref the gvalue had
  15. # gvalue.unset
  16. # ```
  17. #
  18. # Lifetime is managed automatically. It doesn't know about all GType values,
  19. # but it does know the ones that libvips uses.
  20. class GValue < FFI::ManagedStruct
  21. layout :gtype, :GType,
  22. :data, [:ulong_long, 2]
  23. # convert an enum value (str/symb/int) into an int ready for libvips
  24. def self.from_nick(gtype, value)
  25. value = value.to_s if value.is_a? Symbol
  26. if value.is_a? String
  27. # libvips expects "-" as a separator in enum names, but "_" is more
  28. # convenient for ruby, eg. :b_w
  29. value = Vips::vips_enum_from_nick "ruby-vips", gtype, value.tr("_", "-")
  30. if value == -1
  31. raise Vips::Error
  32. end
  33. end
  34. value
  35. end
  36. # convert an int enum back into a symbol
  37. def self.to_nick(gtype, enum_value)
  38. enum_name = Vips::vips_enum_nick gtype, enum_value
  39. if enum_name == nil
  40. raise Vips::Error
  41. end
  42. enum_name.to_sym
  43. end
  44. def self.release ptr
  45. # GLib::logger.debug("GObject::GValue::release") {"ptr = #{ptr}"}
  46. ::GObject::g_value_unset ptr
  47. end
  48. # Allocate memory for a GValue and return a class wrapper. Memory will
  49. # be freed automatically when it goes out of scope. The GValue is inited
  50. # to 0, use {GValue.init} to set a type.
  51. #
  52. # @return [GValue] a new gvalue set to 0
  53. def self.alloc
  54. # allocate memory
  55. memory = FFI::MemoryPointer.new GValue
  56. # make this alloc autorelease ... we mustn't release in
  57. # GValue::release, since we are used to wrap GValue pointers
  58. # made by other people
  59. pointer = FFI::Pointer.new GValue, memory
  60. # ... and wrap in a GValue
  61. return GValue.new pointer
  62. end
  63. # Set the type of thing a gvalue can hold.
  64. #
  65. # @param gtype [GType] the type of thing this GValue can hold.
  66. def init gtype
  67. ::GObject::g_value_init self, gtype
  68. end
  69. # Set the value of a GValue. The value is converted to the type of the
  70. # GValue, if possible.
  71. #
  72. # @param value [Any] The value to set
  73. def set value
  74. # GLib::logger.debug("GObject::GValue.set") {
  75. # "value = #{value.inspect[0..50]}"
  76. # }
  77. gtype = self[:gtype]
  78. fundamental = ::GObject::g_type_fundamental gtype
  79. case gtype
  80. when GBOOL_TYPE
  81. ::GObject::g_value_set_boolean self, (value ? 1 : 0)
  82. when GINT_TYPE
  83. ::GObject::g_value_set_int self, value
  84. when GUINT64_TYPE
  85. ::GObject::g_value_set_uint64 self, value
  86. when GDOUBLE_TYPE
  87. ::GObject::g_value_set_double self, value
  88. when GSTR_TYPE
  89. ::GObject::g_value_set_string self, value
  90. when Vips::REFSTR_TYPE
  91. ::Vips::vips_value_set_ref_string self, value
  92. when Vips::ARRAY_INT_TYPE
  93. value = [value] unless value.is_a? Array
  94. Vips::vips_value_set_array_int self, nil, value.length
  95. ptr = Vips::vips_value_get_array_int self, nil
  96. ptr.write_array_of_int32 value
  97. when Vips::ARRAY_DOUBLE_TYPE
  98. value = [value] unless value.is_a? Array
  99. # this will allocate an array in the gvalue
  100. Vips::vips_value_set_array_double self, nil, value.length
  101. # pull the array out and fill it
  102. ptr = Vips::vips_value_get_array_double self, nil
  103. ptr.write_array_of_double value
  104. when Vips::ARRAY_IMAGE_TYPE
  105. value = [value] unless value.is_a? Array
  106. Vips::vips_value_set_array_image self, value.length
  107. ptr = Vips::vips_value_get_array_image self, nil
  108. ptr.write_array_of_pointer value
  109. # the gvalue needs a ref on each of the images
  110. value.each { |image| ::GObject::g_object_ref image }
  111. when Vips::BLOB_TYPE
  112. len = value.bytesize
  113. ptr = GLib::g_malloc len
  114. Vips::vips_value_set_blob self, GLib::G_FREE, ptr, len
  115. ptr.write_bytes value
  116. else
  117. case fundamental
  118. when GFLAGS_TYPE
  119. ::GObject::g_value_set_flags self, value
  120. when GENUM_TYPE
  121. enum_value = GValue.from_nick(self[:gtype], value)
  122. ::GObject::g_value_set_enum self, enum_value
  123. when GOBJECT_TYPE
  124. ::GObject::g_value_set_object self, value
  125. else
  126. raise Vips::Error, "unimplemented gtype for set: " +
  127. "#{::GObject::g_type_name gtype} (#{gtype})"
  128. end
  129. end
  130. end
  131. # Get the value of a GValue. The value is converted to a Ruby type in
  132. # the obvious way.
  133. #
  134. # @return [Any] the value held by the GValue
  135. def get
  136. gtype = self[:gtype]
  137. fundamental = ::GObject::g_type_fundamental gtype
  138. result = nil
  139. case gtype
  140. when GBOOL_TYPE
  141. result = ::GObject::g_value_get_boolean(self) != 0 ? true : false
  142. when GINT_TYPE
  143. result = ::GObject::g_value_get_int self
  144. when GUINT64_TYPE
  145. result = ::GObject::g_value_get_uint64 self
  146. when GDOUBLE_TYPE
  147. result = ::GObject::g_value_get_double self
  148. when GSTR_TYPE
  149. result = ::GObject::g_value_get_string self
  150. when Vips::REFSTR_TYPE
  151. len = Vips::SizeStruct.new
  152. result = ::Vips::vips_value_get_ref_string self, len
  153. when Vips::ARRAY_INT_TYPE
  154. len = Vips::IntStruct.new
  155. array = Vips::vips_value_get_array_int self, len
  156. result = array.get_array_of_int32 0, len[:value]
  157. when Vips::ARRAY_DOUBLE_TYPE
  158. len = Vips::IntStruct.new
  159. array = Vips::vips_value_get_array_double self, len
  160. result = array.get_array_of_double 0, len[:value]
  161. when Vips::ARRAY_IMAGE_TYPE
  162. len = Vips::IntStruct.new
  163. array = Vips::vips_value_get_array_image self, len
  164. result = array.get_array_of_pointer 0, len[:value]
  165. result.map! do |pointer|
  166. ::GObject::g_object_ref pointer
  167. Vips::Image.new pointer
  168. end
  169. when Vips::BLOB_TYPE
  170. len = Vips::SizeStruct.new
  171. array = Vips::vips_value_get_blob self, len
  172. result = array.get_bytes 0, len[:value]
  173. else
  174. case fundamental
  175. when GFLAGS_TYPE
  176. result = ::GObject::g_value_get_flags self
  177. when GENUM_TYPE
  178. enum_value = ::GObject::g_value_get_enum(self)
  179. result = GValue.to_nick self[:gtype], enum_value
  180. when GOBJECT_TYPE
  181. obj = ::GObject::g_value_get_object self
  182. # g_value_get_object() does not add a ref ... we need to add
  183. # one to match the unref in gobject release
  184. ::GObject::g_object_ref obj
  185. result = Vips::Image.new obj
  186. else
  187. raise Vips::Error, "unimplemented gtype for get: " +
  188. "#{::GObject::g_type_name gtype} (#{gtype})"
  189. end
  190. end
  191. # GLib::logger.debug("GObject::GValue.get") {
  192. # "result = #{result.inspect[0..50]}"
  193. # }
  194. return result
  195. end
  196. # Clear the thing held by a GValue.
  197. #
  198. # This happens automatically when a GValue is GCed, but this method can be
  199. # handy if you need to drop a reference explicitly for some reason.
  200. def unset
  201. ::GObject::g_value_unset self
  202. end
  203. end
  204. attach_function :g_value_init, [GValue.ptr, :GType], :void
  205. # we must use a plain :pointer here, since we call this from #release, which
  206. # just gives us the unwrapped pointer, not the ruby class
  207. attach_function :g_value_unset, [:pointer], :void
  208. attach_function :g_value_set_boolean, [GValue.ptr, :int], :void
  209. attach_function :g_value_set_int, [GValue.ptr, :int], :void
  210. attach_function :g_value_set_uint64, [GValue.ptr, :uint64], :void
  211. attach_function :g_value_set_double, [GValue.ptr, :double], :void
  212. attach_function :g_value_set_enum, [GValue.ptr, :int], :void
  213. attach_function :g_value_set_flags, [GValue.ptr, :uint], :void
  214. attach_function :g_value_set_string, [GValue.ptr, :string], :void
  215. attach_function :g_value_set_object, [GValue.ptr, :pointer], :void
  216. attach_function :g_value_get_boolean, [GValue.ptr], :int
  217. attach_function :g_value_get_int, [GValue.ptr], :int
  218. attach_function :g_value_get_uint64, [GValue.ptr], :uint64
  219. attach_function :g_value_get_double, [GValue.ptr], :double
  220. attach_function :g_value_get_enum, [GValue.ptr], :int
  221. attach_function :g_value_get_flags, [GValue.ptr], :int
  222. attach_function :g_value_get_string, [GValue.ptr], :string
  223. attach_function :g_value_get_object, [GValue.ptr], :pointer
  224. # use :pointer rather than GObject.ptr to avoid casting later
  225. attach_function :g_object_set_property,
  226. [:pointer, :string, GValue.ptr], :void
  227. attach_function :g_object_get_property,
  228. [:pointer, :string, GValue.ptr], :void
  229. end