PageRenderTime 1025ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/gitnyasha/zimcreative
Ruby | 355 lines | 256 code | 61 blank | 38 comment | 4 complexity | b6122f246e493603a85aa02352f7bdae MD5 | raw file
  1. # This module provides an interface to the top level bits of libvips
  2. # via ruby-ffi.
  3. #
  4. # Author:: John Cupitt (mailto:jcupitt@gmail.com)
  5. # License:: MIT
  6. require 'ffi'
  7. module Vips
  8. private
  9. # debugging support
  10. attach_function :vips_object_print_all, [], :void
  11. # we must init these by hand, since they are usually made on first image
  12. # create
  13. attach_function :vips_band_format_get_type, [], :GType
  14. attach_function :vips_interpretation_get_type, [], :GType
  15. attach_function :vips_coding_get_type, [], :GType
  16. public
  17. # some handy gtypes
  18. IMAGE_TYPE = GObject::g_type_from_name "VipsImage"
  19. ARRAY_INT_TYPE = GObject::g_type_from_name "VipsArrayInt"
  20. ARRAY_DOUBLE_TYPE = GObject::g_type_from_name "VipsArrayDouble"
  21. ARRAY_IMAGE_TYPE = GObject::g_type_from_name "VipsArrayImage"
  22. REFSTR_TYPE = GObject::g_type_from_name "VipsRefString"
  23. BLOB_TYPE = GObject::g_type_from_name "VipsBlob"
  24. BAND_FORMAT_TYPE = Vips::vips_band_format_get_type
  25. INTERPRETATION_TYPE = Vips::vips_interpretation_get_type
  26. CODING_TYPE = Vips::vips_coding_get_type
  27. if Vips::at_least_libvips?(8, 6)
  28. attach_function :vips_blend_mode_get_type, [], :GType
  29. BLEND_MODE_TYPE = Vips::vips_blend_mode_get_type
  30. else
  31. BLEND_MODE_TYPE = nil
  32. end
  33. private
  34. class Progress < FFI::Struct
  35. layout :im, :pointer,
  36. :run, :int,
  37. :eta, :int,
  38. :tpels, :int64_t,
  39. :npels, :int64_t,
  40. :percent, :int,
  41. :start, :pointer
  42. end
  43. # Our signal marshalers.
  44. #
  45. # These are functions which take the handler as a param and return a
  46. # closure with the right FFI signature for g_signal_connect for this
  47. # specific signal.
  48. #
  49. # ruby-ffi makes it hard to use the g_signal_connect user data param
  50. # to pass the function pointer through, unfortunately.
  51. #
  52. # We can't throw exceptions across C, so we must catch everything.
  53. MARSHAL_PROGRESS = Proc.new do |handler|
  54. FFI::Function.new(:void, [:pointer, :pointer, :pointer]) do |vi, prog, cb|
  55. begin
  56. handler.(Progress.new(prog))
  57. rescue Exception => e
  58. puts "progress: #{e}"
  59. end
  60. end
  61. end
  62. MARSHAL_READ = Proc.new do |handler|
  63. FFI::Function.new(:int64_t, [:pointer, :pointer, :int64_t]) do |i, p, len|
  64. begin
  65. result = handler.(p, len)
  66. rescue Exception => e
  67. puts "read: #{e}"
  68. result = 0
  69. end
  70. result
  71. end
  72. end
  73. MARSHAL_SEEK = Proc.new do |handler|
  74. FFI::Function.new(:int64_t, [:pointer, :int64_t, :int]) do |i, off, whence|
  75. begin
  76. result = handler.(off, whence)
  77. rescue Exception => e
  78. puts "seek: #{e}"
  79. result = -1
  80. end
  81. result
  82. end
  83. end
  84. MARSHAL_WRITE = Proc.new do |handler|
  85. FFI::Function.new(:int64_t, [:pointer, :pointer, :int64_t]) do |i, p, len|
  86. begin
  87. result = handler.(p, len)
  88. rescue Exception => e
  89. puts "write: #{e}"
  90. result = 0
  91. end
  92. result
  93. end
  94. end
  95. MARSHAL_FINISH = Proc.new do |handler|
  96. FFI::Function.new(:void, [:pointer, :pointer]) do |i, cb|
  97. begin
  98. handler.()
  99. rescue Exception => e
  100. puts "finish: #{e}"
  101. end
  102. end
  103. end
  104. # map signal name to marshal proc
  105. MARSHAL_ALL = {
  106. :preeval => MARSHAL_PROGRESS,
  107. :eval => MARSHAL_PROGRESS,
  108. :posteval => MARSHAL_PROGRESS,
  109. :read => MARSHAL_READ,
  110. :seek => MARSHAL_SEEK,
  111. :write => MARSHAL_WRITE,
  112. :finish => MARSHAL_FINISH,
  113. }
  114. attach_function :vips_enum_from_nick, [:string, :GType, :string], :int
  115. attach_function :vips_enum_nick, [:GType, :int], :string
  116. attach_function :vips_value_set_ref_string,
  117. [GObject::GValue.ptr, :string], :void
  118. attach_function :vips_value_set_array_double,
  119. [GObject::GValue.ptr, :pointer, :int], :void
  120. attach_function :vips_value_set_array_int,
  121. [GObject::GValue.ptr, :pointer, :int], :void
  122. attach_function :vips_value_set_array_image,
  123. [GObject::GValue.ptr, :int], :void
  124. callback :free_fn, [:pointer], :void
  125. attach_function :vips_value_set_blob,
  126. [GObject::GValue.ptr, :free_fn, :pointer, :size_t], :void
  127. class SizeStruct < FFI::Struct
  128. layout :value, :size_t
  129. end
  130. class IntStruct < FFI::Struct
  131. layout :value, :int
  132. end
  133. attach_function :vips_value_get_ref_string,
  134. [GObject::GValue.ptr, SizeStruct.ptr], :string
  135. attach_function :vips_value_get_array_double,
  136. [GObject::GValue.ptr, IntStruct.ptr], :pointer
  137. attach_function :vips_value_get_array_int,
  138. [GObject::GValue.ptr, IntStruct.ptr], :pointer
  139. attach_function :vips_value_get_array_image,
  140. [GObject::GValue.ptr, IntStruct.ptr], :pointer
  141. attach_function :vips_value_get_blob,
  142. [GObject::GValue.ptr, SizeStruct.ptr], :pointer
  143. attach_function :type_find, :vips_type_find, [:string, :string], :GType
  144. class Object < GObject::GObject
  145. # print all active VipsObjects, with their reference counts. Handy for
  146. # debugging ruby-vips.
  147. def self.print_all
  148. GC.start
  149. Vips::vips_object_print_all
  150. end
  151. # the layout of the VipsObject struct
  152. module ObjectLayout
  153. def self.included base
  154. base.class_eval do
  155. # don't actually need most of these
  156. layout :parent, GObject::GObject::Struct,
  157. :constructed, :int,
  158. :static_object, :int,
  159. :argument_table, :pointer,
  160. :nickname, :string,
  161. :description, :string,
  162. :preclose, :int,
  163. :close, :int,
  164. :postclose, :int,
  165. :local_memory, :size_t
  166. end
  167. end
  168. end
  169. class Struct < GObject::GObject::Struct
  170. include ObjectLayout
  171. end
  172. class ManagedStruct < GObject::GObject::ManagedStruct
  173. include ObjectLayout
  174. end
  175. # return a pspec, or nil ... nil wil leave a message in the error log
  176. # which you must clear
  177. def get_pspec name
  178. ppspec = GObject::GParamSpecPtr.new
  179. argument_class = Vips::ArgumentClassPtr.new
  180. argument_instance = Vips::ArgumentInstancePtr.new
  181. result = Vips::vips_object_get_argument self, name,
  182. ppspec, argument_class, argument_instance
  183. return nil if result != 0
  184. ppspec[:value]
  185. end
  186. # return a gtype, raise an error on not found
  187. def get_typeof_error name
  188. pspec = get_pspec name
  189. raise Vips::Error unless pspec
  190. pspec[:value_type]
  191. end
  192. # return a gtype, 0 on not found
  193. def get_typeof name
  194. pspec = get_pspec name
  195. unless pspec
  196. Vips::vips_error_clear
  197. return 0
  198. end
  199. pspec[:value_type]
  200. end
  201. def get name
  202. gtype = get_typeof_error name
  203. gvalue = GObject::GValue.alloc
  204. gvalue.init gtype
  205. GObject::g_object_get_property self, name, gvalue
  206. result = gvalue.get
  207. gvalue.unset
  208. GLib::logger.debug("Vips::Object.get") { "#{name} == #{result}" }
  209. return result
  210. end
  211. def set name, value
  212. GLib::logger.debug("Vips::Object.set") { "#{name} = #{value}" }
  213. gtype = get_typeof_error name
  214. gvalue = GObject::GValue.alloc
  215. gvalue.init gtype
  216. gvalue.set value
  217. GObject::g_object_set_property self, name, gvalue
  218. gvalue.unset
  219. end
  220. def signal_connect name, handler=nil
  221. marshal = MARSHAL_ALL[name.to_sym]
  222. raise Vips::Error, "unsupported signal #{name}" if marshal == nil
  223. if block_given?
  224. # This will grab any block given to us and make it into a proc
  225. prc = Proc.new
  226. elsif handler
  227. # We assume the hander is a proc (perhaps we should test)
  228. prc = handler
  229. else
  230. raise Vips::Error, "must supply either block or handler"
  231. end
  232. # The marshal function will make a closure with the right type signature
  233. # for the selected signal
  234. callback = marshal.(prc)
  235. # we need to make sure this is not GCd while self is alive
  236. @references << callback
  237. GObject::g_signal_connect_data(self, name.to_s, callback, nil, nil, 0)
  238. end
  239. end
  240. class ObjectClass < FFI::Struct
  241. # opaque
  242. end
  243. class Argument < FFI::Struct
  244. layout :pspec, GObject::GParamSpec.ptr
  245. end
  246. class ArgumentInstance < Argument
  247. layout :parent, Argument
  248. # rest opaque
  249. end
  250. # enum VipsArgumentFlags
  251. ARGUMENT_REQUIRED = 1
  252. ARGUMENT_CONSTRUCT = 2
  253. ARGUMENT_SET_ONCE = 4
  254. ARGUMENT_SET_ALWAYS = 8
  255. ARGUMENT_INPUT = 16
  256. ARGUMENT_OUTPUT = 32
  257. ARGUMENT_DEPRECATED = 64
  258. ARGUMENT_MODIFY = 128
  259. ARGUMENT_FLAGS = {
  260. required: ARGUMENT_REQUIRED,
  261. construct: ARGUMENT_CONSTRUCT,
  262. set_once: ARGUMENT_SET_ONCE,
  263. set_always: ARGUMENT_SET_ALWAYS,
  264. input: ARGUMENT_INPUT,
  265. output: ARGUMENT_OUTPUT,
  266. deprecated: ARGUMENT_DEPRECATED,
  267. modify: ARGUMENT_MODIFY
  268. }
  269. class ArgumentClass < Argument
  270. layout :parent, Argument,
  271. :object_class, ObjectClass.ptr,
  272. :flags, :uint,
  273. :priority, :int,
  274. :offset, :ulong_long
  275. end
  276. class ArgumentClassPtr < FFI::Struct
  277. layout :value, ArgumentClass.ptr
  278. end
  279. class ArgumentInstancePtr < FFI::Struct
  280. layout :value, ArgumentInstance.ptr
  281. end
  282. # just use :pointer, not VipsObject.ptr, to avoid casting gobject
  283. # subclasses
  284. attach_function :vips_object_get_argument,
  285. [:pointer, :string,
  286. GObject::GParamSpecPtr.ptr,
  287. ArgumentClassPtr.ptr, ArgumentInstancePtr.ptr],
  288. :int
  289. attach_function :vips_object_print_all, [], :void
  290. attach_function :vips_object_set_from_string, [:pointer, :string], :int
  291. callback :type_map_fn, [:GType, :pointer], :pointer
  292. attach_function :vips_type_map, [:GType, :type_map_fn, :pointer], :pointer
  293. attach_function :vips_object_get_description, [:pointer], :string
  294. end