ruby-vips 1.0.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,9 +6,6 @@ module Vips
6
6
  # * `:sequential` means requests will be top-to-bottom, but with some
7
7
  # amount of buffering behind the read point for small non-local
8
8
  # accesses.
9
- #
10
- # * `:sequential_unbuffered` means requests will be strictly
11
- # top-to-bottom with no read-behind. This can save some memory.
12
- class Access
9
+ class Access < Symbol
13
10
  end
14
11
  end
@@ -1,11 +1,11 @@
1
1
  module Vips
2
2
 
3
- # Various types of alignment. See {Vips::Image.join}, for example.
3
+ # Various types of alignment. See {Image#join}, for example.
4
4
  #
5
5
  # * `:low` Align on the low coordinate edge
6
6
  # * `:centre` Align on the centre
7
7
  # * `:high` Align on the high coordinate edge
8
8
 
9
- class Align
9
+ class Align < Symbol
10
10
  end
11
11
  end
@@ -1,12 +1,12 @@
1
1
  module Vips
2
2
 
3
- # Various fixed 90 degree rotation angles. See {Vips::Image.rot}.
3
+ # Various fixed 90 degree rotation angles. See {Image#rot}.
4
4
  #
5
5
  # * `:d0` no rotate
6
6
  # * `:d90` 90 degrees clockwise
7
7
  # * `:d180` 180 degrees
8
8
  # * `:d270` 90 degrees anti-clockwise
9
9
 
10
- class Angle
10
+ class Angle < Symbol
11
11
  end
12
12
  end
@@ -1,6 +1,6 @@
1
1
  module Vips
2
2
 
3
- # Various fixed 45 degree rotation angles. See {Vips::Image.rot45}.
3
+ # Various fixed 45 degree rotation angles. See {Image#rot45}.
4
4
  #
5
5
  # * `:d0` no rotate
6
6
  # * `:d45` 45 degrees clockwise
@@ -11,6 +11,6 @@ module Vips
11
11
  # * `:d270` 90 degrees anti-clockwise
12
12
  # * `:d315` 45 degrees anti-clockwise
13
13
 
14
- class Angle45
14
+ class Angle45 < Symbol
15
15
  end
16
16
  end
@@ -14,7 +14,7 @@ module Vips
14
14
  # * `:complex` complex (two floats) format
15
15
  # * `:double` double float format
16
16
  # * `:dpcomplex` double complex (two double) format
17
- class BandFormat
17
+ class BandFormat < Symbol
18
18
  end
19
19
 
20
20
  end
@@ -9,6 +9,6 @@ module Vips
9
9
  # * `:none` pixels are not coded
10
10
  # * `:labq` pixels encode 3 float CIELAB values as 4 uchar
11
11
  # * `:rad` pixels encode 3 float RGB as 4 uchar (Radiance coding)
12
- class Coding
12
+ class Coding < Symbol
13
13
  end
14
14
  end
@@ -1,11 +1,11 @@
1
1
  module Vips
2
2
 
3
- # Operations like {Vips::Image.flip} need to be told whether to flip
3
+ # Operations like {Image#flip} need to be told whether to flip
4
4
  # left-right or top-bottom.
5
5
  #
6
6
  # * `:horizontal` left-right
7
7
  # * `:vertical` top-bottom
8
8
 
9
- class Direction
9
+ class Direction < Symbol
10
10
  end
11
11
  end
@@ -2,21 +2,16 @@ module Vips
2
2
 
3
3
  # When the edges of an image are extended, you can specify
4
4
  # how you want the extension done.
5
- # See {Vips::Image.embed}, {Vips::Image.conv}, {Vips::Image.affine} and
5
+ # See {Image#embed}, {Image#conv}, {Image#affine} and
6
6
  # so on.
7
7
  #
8
- # * `:black` new pixels are black, ie. all bits are zero.
9
- #
10
- # * `:copy` each new pixel takes the value of the nearest edge pixel
11
- #
12
- # * `:repeat` the image is tiled to fill the new area
13
- #
14
- # * `:mirror` the image is reflected and tiled to reduce hash edges
15
- #
16
- # * `:white` new pixels are white, ie. all bits are set
17
- #
18
- # * `:background` colour set from the @background property
8
+ # * `:black` new pixels are black, ie. all bits are zero.
9
+ # * `:copy` each new pixel takes the value of the nearest edge pixel
10
+ # * `:repeat` the image is tiled to fill the new area
11
+ # * `:mirror` the image is reflected and tiled to reduce hash edges
12
+ # * `:white` new pixels are white, ie. all bits are set
13
+ # * `:background` colour set from the @background property
19
14
 
20
- class Extend
15
+ class Extend < Symbol
21
16
  end
22
17
  end
@@ -0,0 +1,121 @@
1
+ # This module provides an interface to the top level bits of GObject
2
+ # via ruby-ffi.
3
+ #
4
+ # Author:: John Cupitt (mailto:jcupitt@gmail.com)
5
+ # License:: MIT
6
+
7
+ require 'ffi'
8
+ require 'forwardable'
9
+
10
+ module GObject
11
+
12
+ # we have a number of things we need to inherit in different ways:
13
+ #
14
+ # - we want to be able to subclass GObject in Ruby in a simple way
15
+ # - the layouts of the nested structs need to inherit
16
+ # - we need to be able to cast between structs which share a base struct
17
+ # without creating new wrappers or messing up refcounting
18
+ # - we need automatic gobject refcounting
19
+ #
20
+ # the solution is to split the class into four areas which we treat
21
+ # differently:
22
+ #
23
+ # - we have a "wrapper" Ruby class to allow easy subclassing ... this has a
24
+ # @struct member which holds the actual pointer
25
+ # - we use "forwardable" to forward the various ffi methods on to the
26
+ # @struct member ... we arrange things so that subclasses do not need to
27
+ # do the forwarding themselves
28
+ # - we have two versions of the struct: a plain one which we can use for
29
+ # casting that will not change the refcounts
30
+ # - and a managed one with an unref which we just use for .new
31
+ # - we separate the struct layout into a separate module to avoid repeating
32
+ # ourselves
33
+
34
+ class GObject
35
+ extend Forwardable
36
+ extend SingleForwardable
37
+
38
+ def_instance_delegators :@struct, :[], :to_ptr
39
+ def_single_delegators :ffi_struct, :ptr
40
+
41
+ # the layout of the GObject struct
42
+ module GObjectLayout
43
+ def self.included base
44
+ base.class_eval do
45
+ layout :g_type_instance, :pointer,
46
+ :ref_count, :uint,
47
+ :qdata, :pointer
48
+ end
49
+ end
50
+ end
51
+
52
+ # the struct with unref ... manage object lifetime with this
53
+ class ManagedStruct < FFI::ManagedStruct
54
+ include GObjectLayout
55
+
56
+ def self.release ptr
57
+ # Vips::log "GObject::GObject::ManagedStruct.release: " +
58
+ # "unreffing #{ptr}"
59
+ GObject::g_object_unref ptr
60
+ end
61
+ end
62
+
63
+ # the plain struct ... cast with this
64
+ class Struct < FFI::Struct
65
+ include GObjectLayout
66
+
67
+ end
68
+
69
+ # don't allow ptr == nil, we never want to allocate a GObject struct
70
+ # ourselves, we just want to wrap GLib-allocated GObjects
71
+ #
72
+ # here we use ManagedStruct, not Struct, since this is the ref that will
73
+ # need the unref
74
+ def initialize ptr
75
+ # Vips::log "GObject::GObject.initialize: ptr = #{ptr}"
76
+ @struct = ffi_managed_struct.new ptr
77
+ end
78
+
79
+ # access to the casting struct for this class
80
+ def ffi_struct
81
+ self.class.ffi_struct
82
+ end
83
+
84
+ class << self
85
+ def ffi_struct
86
+ self.const_get :Struct
87
+ end
88
+ end
89
+
90
+ # access to the managed struct for this class
91
+ def ffi_managed_struct
92
+ self.class.ffi_managed_struct
93
+ end
94
+
95
+ class << self
96
+ def ffi_managed_struct
97
+ self.const_get :ManagedStruct
98
+ end
99
+ end
100
+
101
+ end
102
+
103
+ class GParamSpec < FFI::Struct
104
+ # the first few public fields
105
+ layout :g_type_instance, :pointer,
106
+ :name, :string,
107
+ :flags, :uint,
108
+ :value_type, :GType,
109
+ :owner_type, :GType
110
+ end
111
+
112
+ attach_function :g_param_spec_get_blurb, [GParamSpec.ptr], :string
113
+
114
+ attach_function :g_object_ref, [:pointer], :void
115
+ attach_function :g_object_unref, [:pointer], :void
116
+
117
+ class GParamSpecPtr < FFI::Struct
118
+ layout :value, GParamSpec.ptr
119
+ end
120
+
121
+ end
@@ -0,0 +1,251 @@
1
+ # This module provides an interface GValue via ruby-ffi.
2
+ #
3
+ # Author:: John Cupitt (mailto:jcupitt@gmail.com)
4
+ # License:: MIT
5
+
6
+ require 'ffi'
7
+
8
+ module GObject
9
+
10
+ # Represent a GValue. Example use:
11
+ #
12
+ # ```ruby
13
+ # gvalue = GValue::alloc
14
+ # gvalue.init GObject::GDOUBLE_TYPE
15
+ # gvalue.set 3.1415
16
+ # value = gvalue.get
17
+ # ```
18
+ #
19
+ # Lifetime is managed automatically. It doesn't know about all GType values,
20
+ # but it does know the ones that libvips uses.
21
+
22
+ class GValue < FFI::ManagedStruct
23
+ layout :gtype, :GType,
24
+ :data, [:ulong_long, 2]
25
+
26
+ def self.release ptr
27
+ # Vips::log "GObject::GValue::release ptr = #{ptr}"
28
+ ::GObject::g_value_unset ptr
29
+ end
30
+
31
+ # Allocate memory for a GValue and return a class wrapper. Memory will
32
+ # be freed automatically when it goes out of scope. The GValue is inited
33
+ # to 0, use {GValue.init} to set a type.
34
+ #
35
+ # @return [GValue] a new gvalue set to 0
36
+ def self.alloc
37
+ # allocate memory
38
+ memory = FFI::MemoryPointer.new GValue
39
+
40
+ # make this alloc autorelease ... we mustn't release in
41
+ # GValue::release, since we are used to wrap GValue pointers
42
+ # made by other people
43
+ pointer = FFI::Pointer.new GValue, memory
44
+
45
+ # ... and wrap in a GValue
46
+ return GValue.new pointer
47
+ end
48
+
49
+ # Set the type of thing a gvalue can hold.
50
+ #
51
+ # @param gtype [GType] the type of thing this GValue can hold.
52
+ def init gtype
53
+ ::GObject::g_value_init self, gtype
54
+ end
55
+
56
+ # Set the value of a GValue. The value is converted to the type of the
57
+ # GValue, if possible.
58
+ #
59
+ # @param value [Any] The value to set
60
+ def set value
61
+ # Vips::log "GObject::GValue.set: value = #{value.inspect[0..50]}"
62
+
63
+ gtype = self[:gtype]
64
+ fundamental = ::GObject::g_type_fundamental gtype
65
+
66
+ case gtype
67
+ when GBOOL_TYPE
68
+ ::GObject::g_value_set_boolean self, (value ? 1 : 0)
69
+
70
+ when GINT_TYPE
71
+ ::GObject::g_value_set_int self, value
72
+
73
+ when GDOUBLE_TYPE
74
+ ::GObject::g_value_set_double self, value
75
+
76
+ when GSTR_TYPE
77
+ # set_string takes a copy, no lifetime worries
78
+ ::GObject::g_value_set_string self, value
79
+
80
+ when Vips::ARRAY_INT_TYPE
81
+ value = [value] if not value.is_a? Array
82
+
83
+ Vips::vips_value_set_array_int self, nil, value.length
84
+ ptr = Vips::vips_value_get_array_int self, nil
85
+ ptr.write_array_of_int32 value
86
+
87
+ when Vips::ARRAY_DOUBLE_TYPE
88
+ value = [value] if not value.is_a? Array
89
+
90
+ # this will allocate an array in the gvalue
91
+ Vips::vips_value_set_array_double self, nil, value.length
92
+
93
+ # pull the array out and fill it
94
+ ptr = Vips::vips_value_get_array_double self, nil
95
+
96
+ ptr.write_array_of_double value
97
+
98
+ when Vips::ARRAY_IMAGE_TYPE
99
+ value = [value] if not value.is_a? Array
100
+
101
+ Vips::vips_value_set_array_image self, value.length
102
+ ptr = Vips::vips_value_get_array_image self, nil
103
+ ptr.write_array_of_pointer value
104
+
105
+ # the gvalue needs a ref on each of the images
106
+ value.each {|image| ::GObject::g_object_ref image}
107
+
108
+ when Vips::BLOB_TYPE
109
+ len = value.length
110
+ ptr = GLib::g_malloc len
111
+ Vips::vips_value_set_blob self, GLib::G_FREE, ptr, len
112
+ ptr.write_bytes value
113
+
114
+ else
115
+ case fundamental
116
+ when GFLAGS_TYPE
117
+ ::GObject::g_value_set_flags self, value
118
+
119
+ when GENUM_TYPE
120
+ value = value.to_s if value.is_a? Symbol
121
+
122
+ if value.is_a? String
123
+ value = Vips::vips_enum_from_nick "ruby-vips",
124
+ self[:gtype], value
125
+ if value == -1
126
+ raise Vips::Error
127
+ end
128
+ end
129
+
130
+ ::GObject::g_value_set_enum self, value
131
+
132
+ when GOBJECT_TYPE
133
+ ::GObject::g_value_set_object self, value
134
+
135
+ else
136
+ raise Vips::Error, "unimplemented gtype for set: #{gtype}"
137
+ end
138
+ end
139
+ end
140
+
141
+ # Get the value of a GValue. The value is converted to a Ruby type in
142
+ # the obvious way.
143
+ #
144
+ # @return [Any] the value held by the GValue
145
+ def get
146
+ gtype = self[:gtype]
147
+ fundamental = ::GObject::g_type_fundamental gtype
148
+ result = nil
149
+
150
+ case gtype
151
+ when GBOOL_TYPE
152
+ result = ::GObject::g_value_get_boolean(self) != 0 ? true : false
153
+
154
+ when GINT_TYPE
155
+ result = ::GObject::g_value_get_int self
156
+
157
+ when GDOUBLE_TYPE
158
+ result = ::GObject::g_value_get_double self
159
+
160
+ when GSTR_TYPE
161
+ # FIXME do we need to strdup here?
162
+ result = ::GObject::g_value_get_string self
163
+
164
+ when Vips::ARRAY_INT_TYPE
165
+ len = Vips::IntStruct.new
166
+ array = Vips::vips_value_get_array_int self, len
167
+ result = array.get_array_of_int32 0, len[:value]
168
+
169
+ when Vips::ARRAY_DOUBLE_TYPE
170
+ len = Vips::IntStruct.new
171
+ array = Vips::vips_value_get_array_double self, len
172
+ result = array.get_array_of_double 0, len[:value]
173
+
174
+ when Vips::ARRAY_IMAGE_TYPE
175
+ len = Vips::IntStruct.new
176
+ array = Vips::vips_value_get_array_image self, len
177
+ result = array.get_array_of_pointer 0, len[:value]
178
+ result.map! do |pointer|
179
+ ::GObject::g_object_ref pointer
180
+ Vips::Image.new pointer
181
+ end
182
+
183
+ when Vips::BLOB_TYPE
184
+ len = Vips::SizeStruct.new
185
+ array = Vips::vips_value_get_blob self, len
186
+ result = array.get_bytes 0, len[:value]
187
+
188
+ else
189
+ case fundamental
190
+ when GFLAGS_TYPE
191
+ result = ::GObject::g_value_get_flags self
192
+
193
+ when GENUM_TYPE
194
+ enum_value = ::GObject::g_value_get_enum self
195
+ # this returns a static string, no need to worry about
196
+ # lifetime
197
+ enum_name = Vips::vips_enum_nick self[:gtype], enum_value
198
+ if enum_name == nil
199
+ raise Vips::Error
200
+ end
201
+ result = enum_name.to_sym
202
+
203
+ when GOBJECT_TYPE
204
+ obj = ::GObject::g_value_get_object self
205
+ # g_value_get_object() does not add a ref ... we need to add
206
+ # one to match the unref in gobject release
207
+ ::GObject::g_object_ref obj
208
+ result = Vips::Image.new obj
209
+
210
+ else
211
+ raise Vips::Error, "unimplemented gtype for get: #{gtype}"
212
+
213
+ end
214
+ end
215
+
216
+ # Vips::log "GObject::GValue.get: result = #{result.inspect[0..50]}"
217
+
218
+ return result
219
+ end
220
+
221
+ end
222
+
223
+ attach_function :g_value_init, [GValue.ptr, :GType], :void
224
+
225
+ # we must use a plain :pointer here, since we call this from #release, which
226
+ # just gives us the unwrapped pointer, not the ruby class
227
+ attach_function :g_value_unset, [:pointer], :void
228
+
229
+ attach_function :g_value_set_boolean, [GValue.ptr, :int], :void
230
+ attach_function :g_value_set_int, [GValue.ptr, :int], :void
231
+ attach_function :g_value_set_double, [GValue.ptr, :double], :void
232
+ attach_function :g_value_set_enum, [GValue.ptr, :int], :void
233
+ attach_function :g_value_set_flags, [GValue.ptr, :uint], :void
234
+ attach_function :g_value_set_string, [GValue.ptr, :string], :void
235
+ attach_function :g_value_set_object, [GValue.ptr, :pointer], :void
236
+
237
+ attach_function :g_value_get_boolean, [GValue.ptr], :int
238
+ attach_function :g_value_get_int, [GValue.ptr], :int
239
+ attach_function :g_value_get_double, [GValue.ptr], :double
240
+ attach_function :g_value_get_enum, [GValue.ptr], :int
241
+ attach_function :g_value_get_flags, [GValue.ptr], :int
242
+ attach_function :g_value_get_string, [GValue.ptr], :string
243
+ attach_function :g_value_get_object, [GValue.ptr], :pointer
244
+
245
+ # use :pointer rather than GObject.ptr to avoid casting later
246
+ attach_function :g_object_set_property,
247
+ [:pointer, :string, GValue.ptr], :void
248
+ attach_function :g_object_get_property,
249
+ [:pointer, :string, GValue.ptr], :void
250
+
251
+ end