Skip to content

Commit baa3123

Browse files
authored
improve gflags argument handling (#421)
* improve gflags argument handling * fix lint failure * oops! * add a compat method * throw an error for bad flag * another lint
1 parent 726357f commit baa3123

File tree

5 files changed

+77
-8
lines changed

5 files changed

+77
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## master
44

55
* improve NULL pointer handling [dloebl]
6+
* improve GFlags argument handling [jcupitt]
67

78
## Version 2.2.4 (2025-06-05)
89

lib/vips/gvalue.rb

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class GValue < FFI::ManagedStruct
2525
:data, [:ulong_long, 2]
2626

2727
# convert an enum value (str/symb/int) into an int ready for libvips
28-
def self.from_nick(gtype, value)
28+
def self.enum_from_nick(gtype, value)
2929
value = value.to_s if value.is_a? Symbol
3030

3131
if value.is_a? String
@@ -40,6 +40,43 @@ def self.from_nick(gtype, value)
4040
value
4141
end
4242

43+
# compatibility ... we used to call it this, perhaps someone has used this
44+
# internal method
45+
def self.from_nick(gtype, value)
46+
GValue.enum_from_nick(gtype, value)
47+
end
48+
49+
# convert an flags value (array[str/symb/int] | str/symb/int) into an
50+
# int ready for libvips
51+
def self.flags_from_nick(gtype, value)
52+
if value.is_a? String
53+
# libvips will parse strings like "sub|up" etc.
54+
name = value.tr("_", "-")
55+
value = Vips.vips_flags_from_nick "ruby-vips", gtype, name
56+
else
57+
value = [value] if !value.is_a? Array
58+
59+
# convert each item to a set of bits, OR them together
60+
result = 0
61+
value.map do |item|
62+
item = item.to_s if item.is_a? Symbol
63+
if item.is_a? String
64+
name = item.tr("_", "-")
65+
item = Vips.vips_flags_from_nick "ruby-vips", gtype, name
66+
if item == -1
67+
raise Vips::Error
68+
end
69+
end
70+
71+
result |= item
72+
end
73+
74+
value = result
75+
end
76+
77+
value
78+
end
79+
4380
# convert an int enum back into a symbol
4481
def self.to_nick(gtype, enum_value)
4582
enum_name = Vips.vips_enum_nick gtype, enum_value
@@ -148,10 +185,11 @@ def set value
148185
else
149186
case fundamental
150187
when GFLAGS_TYPE
151-
::GObject.g_value_set_flags self, value
188+
flags_value = GValue.flags_from_nick(self[:gtype], value)
189+
::GObject.g_value_set_flags self, flags_value
152190

153191
when GENUM_TYPE
154-
enum_value = GValue.from_nick(self[:gtype], value)
192+
enum_value = GValue.enum_from_nick(self[:gtype], value)
155193
::GObject.g_value_set_enum self, enum_value
156194

157195
when GOBJECT_TYPE

lib/vips/image.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,12 @@ def self.smap x, &block
114114
end
115115

116116
def self.complex? format
117-
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
117+
format_number = GObject::GValue.enum_from_nick BAND_FORMAT_TYPE, format
118118
Vips.vips_band_format_iscomplex(format_number) != 0
119119
end
120120

121121
def self.float? format
122-
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
122+
format_number = GObject::GValue.enum_from_nick BAND_FORMAT_TYPE, format
123123
Vips.vips_band_format_isfloat(format_number) != 0
124124
end
125125

@@ -380,7 +380,7 @@ def self.new_from_memory data, width, height, bands, format
380380
size = data.bytesize
381381
end
382382

383-
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
383+
format_number = GObject::GValue.enum_from_nick BAND_FORMAT_TYPE, format
384384
vi = Vips.vips_image_new_from_memory data, size,
385385
width, height, bands, format_number
386386
raise Vips::Error if vi.null?
@@ -405,7 +405,7 @@ def self.new_from_memory data, width, height, bands, format
405405
# @param format [Symbol] band format
406406
# @return [Image] the loaded image
407407
def self.new_from_memory_copy data, width, height, bands, format
408-
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
408+
format_number = GObject::GValue.enum_from_nick BAND_FORMAT_TYPE, format
409409

410410
if data.is_a?(FFI::Pointer)
411411
if data.size == UNKNOWN_POINTER_SIZE
@@ -1319,7 +1319,7 @@ def composite overlay, mode, **opts
13191319
end
13201320

13211321
mode = mode.map do |x|
1322-
GObject::GValue.from_nick Vips::BLEND_MODE_TYPE, x
1322+
GObject::GValue.enum_from_nick Vips::BLEND_MODE_TYPE, x
13231323
end
13241324

13251325
Vips::Image.composite([self] + overlay, mode, **opts)

lib/vips/object.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class Progress < FFI::Struct
125125

126126
attach_function :vips_enum_from_nick, [:string, :GType, :string], :int
127127
attach_function :vips_enum_nick, [:GType, :int], :string
128+
attach_function :vips_flags_from_nick, [:string, :GType, :string], :int
128129

129130
attach_function :vips_value_set_ref_string,
130131
[GObject::GValue.ptr, :string], :void

spec/vips_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,35 @@
166166
expect(rot.bands).to eq(1)
167167
end
168168

169+
it "can handle symbol flag arguments" do
170+
black = Vips::Operation.call "black", [200, 200]
171+
bytes = Vips::Operation.call "pngsave_buffer", [black], keep: :icc
172+
173+
expect(bytes.length).to be > 100
174+
end
175+
176+
it "can handle int flag arguments" do
177+
black = Vips::Operation.call "black", [200, 200]
178+
bytes = Vips::Operation.call "pngsave_buffer", [black], keep: 1 << 3
179+
180+
expect(bytes.length).to be > 100
181+
end
182+
183+
it "can handle string flag arguments" do
184+
black = Vips::Operation.call "black", [200, 200]
185+
bytes = Vips::Operation.call "pngsave_buffer", [black], keep: "icc"
186+
187+
expect(bytes.length).to be > 100
188+
end
189+
190+
it "can handle array flag arguments" do
191+
black = Vips::Operation.call "black", [200, 200]
192+
bytes = Vips::Operation.call "pngsave_buffer", [black],
193+
keep: [:icc, :xmp]
194+
195+
expect(bytes.length).to be > 100
196+
end
197+
169198
it "can return optional output args" do
170199
point = Vips::Operation.call "black", [1, 1]
171200
test = Vips::Operation.call "embed", [point, 20, 10, 100, 100],

0 commit comments

Comments
 (0)