208 lines
4.9 KiB
Python
Executable File
208 lines
4.9 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
# walk vips and generate member definitions for all operators
|
|
|
|
# sample member definition:
|
|
|
|
# VImage VImage::invert( VOption *options )
|
|
# {
|
|
# VImage out;
|
|
#
|
|
# call( "invert",
|
|
# (options ? options : VImage::option())->
|
|
# set( "in", *this )->
|
|
# set( "out", &out ) );
|
|
#
|
|
# return( out );
|
|
# }
|
|
|
|
import sys
|
|
import re
|
|
|
|
import logging
|
|
#logging.basicConfig(level = logging.DEBUG)
|
|
|
|
import gi
|
|
gi.require_version('Vips', '8.0')
|
|
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>",
|
|
"VipsBlob" : "VipsBlob *"
|
|
}
|
|
|
|
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
|
|
if flags & Vips.ArgumentFlags.DEPRECATED:
|
|
continue
|
|
|
|
required.append(prop)
|
|
|
|
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)
|
|
|
|
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)
|
|
|
|
def gen_arg_list(op, required):
|
|
first = True
|
|
for prop in required:
|
|
if not first:
|
|
print ',',
|
|
else:
|
|
first = False
|
|
|
|
print get_ctype(prop),
|
|
|
|
# output params are passed by reference
|
|
flags = op.get_argument_flags(prop.name)
|
|
if flags & Vips.ArgumentFlags.OUTPUT:
|
|
print '*',
|
|
|
|
print cppize(prop.name),
|
|
|
|
if not first:
|
|
print ',',
|
|
print 'VOption *options',
|
|
|
|
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)
|
|
|
|
if result == None:
|
|
print 'void',
|
|
else:
|
|
print '%s' % gtype_to_cpp[result.value_type.name],
|
|
|
|
print 'VImage::%s(' % nickname,
|
|
|
|
gen_arg_list(op, required)
|
|
|
|
print ')'
|
|
print '{'
|
|
if result != None:
|
|
print ' %s %s;' % (get_ctype(result), cppize(result.name))
|
|
print ''
|
|
|
|
print ' call( "%s"' % nickname,
|
|
|
|
first = True
|
|
for prop in all_required:
|
|
if first:
|
|
print ','
|
|
print ' (options ? options : VImage::option())',
|
|
first = False
|
|
|
|
print '->'
|
|
print ' ',
|
|
if prop == this:
|
|
print 'set( "%s", *this )' % prop.name,
|
|
else:
|
|
flags = op.get_argument_flags(prop.name)
|
|
arg = cppize(prop.name)
|
|
if flags & Vips.ArgumentFlags.OUTPUT and prop == result:
|
|
arg = '&' + arg
|
|
|
|
print 'set( "%s", %s )' % (prop.name, arg),
|
|
|
|
print ');'
|
|
|
|
if result != None:
|
|
print ''
|
|
print ' return( %s );' % cppize(result.name)
|
|
|
|
print '}'
|
|
print ''
|
|
|
|
# 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:
|
|
find_class_methods(child)
|
|
|
|
if __name__ == '__main__':
|
|
find_class_methods(vips_type_operation)
|
|
|