libvips/cplusplus/gen-operators.py

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)