2014-10-27 19:17:49 +01:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
|
|
|
# walk vips and generate headers for all operators
|
|
|
|
|
|
|
|
# sample member declaration :
|
|
|
|
|
|
|
|
# VImage invert( VOption *options = 0 )
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import re
|
|
|
|
|
|
|
|
import logging
|
|
|
|
#logging.basicConfig(level = logging.DEBUG)
|
|
|
|
|
2016-07-24 15:47:22 +02:00
|
|
|
import gi
|
|
|
|
gi.require_version('Vips', '8.0')
|
2014-10-27 19:17:49 +01:00
|
|
|
from gi.repository import Vips, GObject
|
|
|
|
|
|
|
|
vips_type_image = GObject.GType.from_name("VipsImage")
|
|
|
|
vips_type_operation = GObject.GType.from_name("VipsOperation")
|
|
|
|
param_enum = GObject.GType.from_name("GParamEnum")
|
|
|
|
|
|
|
|
# turn a GType into a C++ type
|
|
|
|
gtype_to_cpp = {
|
|
|
|
"VipsImage" : "VImage",
|
|
|
|
"gint" : "int",
|
|
|
|
"gdouble" : "double",
|
|
|
|
"gboolean" : "bool",
|
|
|
|
"gchararray" : "char *",
|
|
|
|
"VipsArrayDouble" : "std::vector<double>",
|
|
|
|
"VipsArrayImage" : "std::vector<VImage>",
|
2014-10-28 11:12:06 +01:00
|
|
|
"VipsBlob" : "VipsBlob *"
|
2014-10-27 19:17:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
def get_ctype(prop):
|
|
|
|
# enum params use the C name as their name
|
|
|
|
if GObject.type_is_a(param_enum, prop):
|
|
|
|
return prop.value_type.name
|
|
|
|
|
|
|
|
return gtype_to_cpp[prop.value_type.name]
|
|
|
|
|
|
|
|
def find_required(op):
|
|
|
|
required = []
|
|
|
|
for prop in op.props:
|
|
|
|
flags = op.get_argument_flags(prop.name)
|
|
|
|
if not flags & Vips.ArgumentFlags.REQUIRED:
|
|
|
|
continue
|
2014-11-16 13:19:04 +01:00
|
|
|
if flags & Vips.ArgumentFlags.DEPRECATED:
|
|
|
|
continue
|
2014-10-27 19:17:49 +01:00
|
|
|
|
|
|
|
required.append(prop)
|
|
|
|
|
2014-11-16 13:19:04 +01:00
|
|
|
def priority_sort(a, b):
|
|
|
|
pa = op.get_argument_priority(a.name)
|
|
|
|
pb = op.get_argument_priority(b.name)
|
|
|
|
|
|
|
|
return pa - pb
|
|
|
|
|
|
|
|
required.sort(priority_sort)
|
|
|
|
|
2014-10-27 19:17:49 +01:00
|
|
|
return required
|
|
|
|
|
|
|
|
# find the first input image ... this will be used as "this"
|
|
|
|
def find_first_input_image(op, required):
|
|
|
|
found = False
|
|
|
|
for prop in required:
|
|
|
|
flags = op.get_argument_flags(prop.name)
|
|
|
|
if not flags & Vips.ArgumentFlags.INPUT:
|
|
|
|
continue
|
|
|
|
if GObject.type_is_a(vips_type_image, prop.value_type):
|
|
|
|
found = True
|
|
|
|
break
|
|
|
|
|
|
|
|
if not found:
|
|
|
|
return None
|
|
|
|
|
|
|
|
return prop
|
|
|
|
|
|
|
|
# find the first output arg ... this will be used as the result
|
|
|
|
def find_first_output(op, required):
|
|
|
|
found = False
|
|
|
|
for prop in required:
|
|
|
|
flags = op.get_argument_flags(prop.name)
|
|
|
|
if not flags & Vips.ArgumentFlags.OUTPUT:
|
|
|
|
continue
|
|
|
|
found = True
|
|
|
|
break
|
|
|
|
|
|
|
|
if not found:
|
|
|
|
return None
|
|
|
|
|
|
|
|
return prop
|
|
|
|
|
|
|
|
# swap any "-" for "_"
|
|
|
|
def cppize(name):
|
|
|
|
return re.sub('-', '_', name)
|
|
|
|
|
2015-01-06 12:51:53 +01:00
|
|
|
def gen_arg_list(op, required):
|
2014-10-27 19:17:49 +01:00
|
|
|
first = True
|
|
|
|
for prop in required:
|
|
|
|
if not first:
|
|
|
|
print ',',
|
|
|
|
else:
|
|
|
|
first = False
|
|
|
|
|
|
|
|
print get_ctype(prop),
|
2015-01-06 12:51:53 +01:00
|
|
|
|
|
|
|
# output params are passed by reference
|
|
|
|
flags = op.get_argument_flags(prop.name)
|
|
|
|
if flags & Vips.ArgumentFlags.OUTPUT:
|
|
|
|
print '*',
|
|
|
|
|
2014-10-27 19:17:49 +01:00
|
|
|
print cppize(prop.name),
|
|
|
|
|
|
|
|
if not first:
|
|
|
|
print ',',
|
|
|
|
print 'VOption *options = 0',
|
|
|
|
|
|
|
|
def gen_operation(cls):
|
|
|
|
op = Vips.Operation.new(cls.name)
|
|
|
|
gtype = Vips.type_find("VipsOperation", cls.name)
|
|
|
|
nickname = Vips.nickname_find(gtype)
|
|
|
|
all_required = find_required(op)
|
|
|
|
|
|
|
|
result = find_first_output(op, all_required)
|
|
|
|
this = find_first_input_image(op, all_required)
|
|
|
|
|
|
|
|
# shallow copy
|
|
|
|
required = all_required[:]
|
|
|
|
if result != None:
|
|
|
|
required.remove(result)
|
|
|
|
if this != None:
|
|
|
|
required.remove(this)
|
|
|
|
|
|
|
|
# no "this" available, it's a class method
|
|
|
|
if this == None:
|
|
|
|
print 'static',
|
|
|
|
|
|
|
|
if result == None:
|
|
|
|
print 'void',
|
|
|
|
else:
|
|
|
|
print '%s' % gtype_to_cpp[result.value_type.name],
|
|
|
|
|
|
|
|
print '%s(' % nickname,
|
|
|
|
|
2015-01-06 12:51:53 +01:00
|
|
|
gen_arg_list(op, required)
|
2014-10-27 19:17:49 +01:00
|
|
|
|
2016-01-09 15:52:05 +01:00
|
|
|
print ');'
|
2014-10-27 19:17:49 +01:00
|
|
|
|
|
|
|
# we have a few synonyms ... don't generate twice
|
|
|
|
generated = {}
|
|
|
|
|
|
|
|
def find_class_methods(cls):
|
|
|
|
if not cls.is_abstract():
|
|
|
|
gtype = Vips.type_find("VipsOperation", cls.name)
|
|
|
|
nickname = Vips.nickname_find(gtype)
|
|
|
|
if not nickname in generated:
|
|
|
|
gen_operation(cls)
|
|
|
|
generated[nickname] = True
|
|
|
|
|
|
|
|
if len(cls.children) > 0:
|
|
|
|
for child in cls.children:
|
2014-11-16 13:19:04 +01:00
|
|
|
find_class_methods(child)
|
2014-10-27 19:17:49 +01:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
find_class_methods(vips_type_operation)
|
|
|
|
|