Merge branch 'add-doxygen'

This commit is contained in:
John Cupitt 2020-09-06 14:03:29 +01:00
commit 1864729771
16 changed files with 6579 additions and 2428 deletions

View File

@ -1,5 +1,8 @@
14/8/20 started 8.11
- add vips_jpegload_source() and vips_svgload_source() to public C API
- integrate doxygen in build system to generate C++ API docs
- improve C++ API doc comments
- add VipsInterpolate and guint64 support to C++ API
6/9/20 started 8.10.2
- update magicksave/load profile handling [kelilevi]

View File

@ -239,6 +239,12 @@ AC_PROG_INSTALL
AC_PROG_LN_S
AM_WITH_DMALLOC
AC_CHECK_PROGS([DOXYGEN], [doxygen])
if test -z "$DOXYGEN"; then
AC_MSG_WARN([doxygen not found; C++ docs will not be generated])
fi
AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])
# we need a fully expanded version of $libdir
# without this we get something like
# define VIPS_LIBDIR ${exec_prefix}/lib
@ -248,11 +254,11 @@ test x"$exec_prefix" = x"NONE" && exec_prefix='${prefix}'
# set $expanded_value to the fully-expanded value of the argument
expand () {
eval expanded_value=$1
eval expanded_value=$1
if test x"$expanded_value" != x"$1"; then
expand "$expanded_value"
fi
if test x"$expanded_value" != x"$1"; then
expand "$expanded_value"
fi
}
expand $libdir
@ -1345,6 +1351,7 @@ AC_CONFIG_FILES([
libvips/mosaicing/Makefile
libvips/create/Makefile
libvips/resample/Makefile
cplusplus/Doxyfile
cplusplus/include/Makefile
cplusplus/include/vips/Makefile
cplusplus/Makefile
@ -1379,6 +1386,7 @@ gobject introspection: $found_introspection
enable radiance support: $with_radiance
enable analyze support: $with_analyze
enable PPM support: $with_ppm
generate C++ docs: $DOXYGEN
* optional dependencies
use fftw3 for FFT: $with_fftw

3
cplusplus/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
html
Doxyfile
doxygen.stamp

2589
cplusplus/Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,24 @@ vips-operators.cpp:
echo "// this file is generated automatically, do not edit!" >> vips-operators.cpp; \
./gen-operators.py -g cpp >> vips-operators.cpp
if HAVE_DOXYGEN
html_DATA = html
html: doxygen.stamp
doxygen.stamp: Doxyfile
$(DOXYGEN) $^
touch doxygen.stamp
install-htmlDATA:
-mkdir -p $(DESTDIR)$(htmldir)
-cp -r html $(DESTDIR)$(htmldir)
endif
EXTRA_DIST = \
README \
vips-operators.cpp \
Doxyfile.in \
gen-operators.py

View File

@ -110,19 +110,6 @@ VSource::new_from_options( const char *options )
return( out );
}
VOption *
VOption::set( const char *name, const VSource value )
{
Pair *pair = new Pair( name );
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_SOURCE );
g_value_set_object( &pair->value, value.get_source() );
options.push_back( pair );
return( this );
}
VTarget
VTarget::new_to_descriptor( int descriptor )
{
@ -162,17 +149,4 @@ VTarget::new_to_memory()
return( out );
}
VOption *
VOption::set( const char *name, const VTarget value )
{
Pair *pair = new Pair( name );
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_TARGET );
g_value_set_object( &pair->value, value.get_target() );
options.push_back( pair );
return( this );
}
VIPS_NAMESPACE_END

View File

@ -140,6 +140,20 @@ VOption::set( const char *name, int value )
return( this );
}
// input guint64
VOption *
VOption::set( const char *name, guint64 value )
{
Pair *pair = new Pair( name );
pair->input = true;
g_value_init( &pair->value, G_TYPE_UINT64 );
g_value_set_uint64( &pair->value, value );
options.push_back( pair );
return( this );
}
// input double
VOption *
VOption::set( const char *name, double value )
@ -167,39 +181,17 @@ VOption::set( const char *name, const char *value )
return( this );
}
// input image
// input vips object (image, source, target, etc. etc.)
VOption *
VOption::set( const char *name, const VImage value )
VOption::set( const char *name, const VObject value )
{
Pair *pair = new Pair( name );
VipsObject *object = value.get_object();
GType type = G_VALUE_TYPE( object );
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_IMAGE );
g_value_set_object( &pair->value, value.get_image() );
options.push_back( pair );
return( this );
}
// input double array
VOption *
VOption::set( const char *name, std::vector<double> value )
{
Pair *pair = new Pair( name );
double *array;
unsigned int i;
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_ARRAY_DOUBLE );
vips_value_set_array_double( &pair->value, NULL,
static_cast< int >( value.size() ) );
array = vips_value_get_array_double( &pair->value, NULL );
for( i = 0; i < value.size(); i++ )
array[i] = value[i];
g_value_init( &pair->value, type );
g_value_set_object( &pair->value, object );
options.push_back( pair );
return( this );
@ -229,6 +221,30 @@ VOption::set( const char *name, std::vector<int> value )
return( this );
}
// input double array
VOption *
VOption::set( const char *name, std::vector<double> value )
{
Pair *pair = new Pair( name );
double *array;
unsigned int i;
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_ARRAY_DOUBLE );
vips_value_set_array_double( &pair->value, NULL,
static_cast< int >( value.size() ) );
array = vips_value_get_array_double( &pair->value, NULL );
for( i = 0; i < value.size(); i++ )
array[i] = value[i];
options.push_back( pair );
return( this );
}
// input image array
VOption *
VOption::set( const char *name, std::vector<VImage> value )

View File

@ -60,17 +60,4 @@ VInterpolate::new_from_name( const char *name, VOption *options )
return( out );
}
VOption *
VOption::set( const char *name, const VInterpolate value )
{
Pair *pair = new Pair( name );
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_INTERPOLATE );
g_value_set_object( &pair->value, value.get_interpolate() );
options.push_back( pair );
return( this );
}
VIPS_NAMESPACE_END

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python3
# This file generates the member definitions and declarations for all vips
# operators.
@ -39,6 +39,8 @@ gtype_to_cpp = {
GValue.image_type: 'VImage',
GValue.source_type: 'VSource',
GValue.target_type: 'VTarget',
GValue.guint64_type: 'guint64',
type_from_name('VipsInterpolate'): 'VInterpolate',
GValue.array_int_type: 'std::vector<int>',
GValue.array_double_type: 'std::vector<double>',
GValue.array_image_type: 'std::vector<VImage>',
@ -60,7 +62,7 @@ _OPERATION_DEPRECATED = 8
def get_cpp_type(gtype):
"""Map a gtype to C++ type name we use to represent it.
"""Map a gtype to the C++ type name we use to represent it.
"""
if gtype in gtype_to_cpp:
return gtype_to_cpp[gtype]
@ -85,30 +87,40 @@ def cppize(name):
def generate_operation(operation_name, declaration_only=False):
intro = Introspect.get(operation_name)
required_output = [name for name in intro.required_output if name != intro.member_x]
required_output = [name
for name in intro.required_output if name != intro.member_x]
has_output = len(required_output) >= 1
# Add a C++ style comment block with some additional markings (@param,
# @return)
if declaration_only:
result = '\n/**\n * {}.'.format(intro.description.capitalize())
result = f'\n/**\n * {intro.description.capitalize()}.'
if len(intro.optional_input) > 0:
result += '\n *\n * **Optional parameters**'
for name in intro.optional_input:
details = intro.details[name]
result += f'\n * - **{cppize(name)}** -- '
result += f'{details["blurb"]}, '
result += f'{get_cpp_type(details["type"])}.'
result += '\n *'
for name in intro.method_args:
result += '\n * @param {} {}.' \
.format(cppize(name), intro.details[name]['blurb'])
details = intro.details[name]
result += f'\n * @param {cppize(name)} {details["blurb"]}.'
if has_output:
# skip the first element
for name in required_output[1:]:
result += '\n * @param {} {}.' \
.format(cppize(name), intro.details[name]['blurb'])
details = intro.details[name]
result += f'\n * @param {cppize(name)} {details["blurb"]}.'
result += '\n * @param options Optional options.'
result += '\n * @param options Set of options.'
if has_output:
result += '\n * @return {}.' \
.format(intro.details[required_output[0]]['blurb'])
details = intro.details[required_output[0]]
result += f'\n * @return {details["blurb"]}.'
result += '\n */\n'
else:
@ -120,7 +132,7 @@ def generate_operation(operation_name, declaration_only=False):
# the first output arg will be used as the result
cpp_type = get_cpp_type(intro.details[required_output[0]]['type'])
spacing = '' if cpp_type.endswith(cplusplus_suffixes) else ' '
result += '{0}{1}'.format(cpp_type, spacing)
result += f'{cpp_type}{spacing}'
else:
result += 'void '
@ -131,13 +143,13 @@ def generate_operation(operation_name, declaration_only=False):
if operation_name in cplusplus_keywords:
cplusplus_operation += '_image'
result += '{0}( '.format(cplusplus_operation)
result += f'{cplusplus_operation}( '
for name in intro.method_args:
details = intro.details[name]
gtype = details['type']
cpp_type = get_cpp_type(gtype)
spacing = '' if cpp_type.endswith(cplusplus_suffixes) else ' '
result += '{0}{1}{2}, '.format(cpp_type, spacing, cppize(name))
result += f'{cpp_type}{spacing}{cppize(name)}, '
# output params are passed by reference
if has_output:
@ -147,9 +159,9 @@ def generate_operation(operation_name, declaration_only=False):
gtype = details['type']
cpp_type = get_cpp_type(gtype)
spacing = '' if cpp_type.endswith(cplusplus_suffixes) else ' '
result += '{0}{1}*{2}, '.format(cpp_type, spacing, cppize(name))
result += f'{cpp_type}{spacing}*{cppize(name)}, '
result += 'VOption *options {0})'.format('= 0 ' if declaration_only else '')
result += f'VOption *options {"= 0 " if declaration_only else ""})'
# if no 'this' available, it's a class method and they are all const
if intro.member_x is not None:
@ -167,36 +179,35 @@ def generate_operation(operation_name, declaration_only=False):
name = required_output[0]
cpp_type = get_cpp_type(intro.details[name]['type'])
spacing = '' if cpp_type.endswith(cplusplus_suffixes) else ' '
result += ' {0}{1}{2};\n\n'.format(cpp_type, spacing, cppize(name))
result += f' {cpp_type}{spacing}{cppize(name)};\n\n'
result += ' call( "{0}",\n'.format(operation_name)
result += ' (options ? options : VImage::option())'
result += f' call( "{operation_name}",\n'
result += f' (options ? options : VImage::option())'
if intro.member_x is not None:
result += '->\n'
result += ' set( "{0}", *this )'.format(intro.member_x)
result += f'->\n'
result += f' set( "{intro.member_x}", *this )'
all_required = intro.method_args
if has_output:
# first element needs to be passed by reference
arg = cppize(required_output[0])
result += '->\n'
result += ' set( "{0}", &{1} )' \
.format(required_output[0], arg)
result += f'->\n'
result += f' set( "{required_output[0]}", &{arg} )'
# append the remaining list
all_required += required_output[1:]
for name in all_required:
arg = cppize(name)
result += '->\n'
result += ' set( "{0}", {1} )'.format(name, arg)
result += f'->\n'
result += f' set( "{name}", {arg} )'
result += ' );\n'
if has_output:
result += '\n'
result += ' return( {0} );\n'.format(required_output[0])
result += f'\n'
result += f' return( {required_output[0]} );\n'
result += '}'

View File

@ -3,8 +3,7 @@ pkginclude_HEADERS = \
VImage8.h \
VInterpolate8.h \
VConnection8.h \
vips8 \
vips-operators.h
vips8
vips-operators.h:
echo "// headers for vips operations" > vips-operators.h; \

View File

@ -34,7 +34,7 @@
VIPS_NAMESPACE_START
class VSource : VObject
class VSource : public VObject
{
public:
VSource( VipsSource *input, VSteal steal = STEAL ) :
@ -66,7 +66,7 @@ public:
};
class VTarget : VObject
class VTarget : public VObject
{
public:
VTarget( VipsTarget *output, VSteal steal = STEAL ) :

View File

@ -39,16 +39,35 @@
VIPS_NAMESPACE_START
/**
* The libvips error class. It holds a single string containing an
* internationalized error message in utf-8 encoding.
*/
class VIPS_CPLUSPLUS_API VError : public std::exception {
std::string _what;
public:
/**
* Construct a VError, setting the error message.
*/
VError( const std::string &what ) : _what( what ) {}
/**
* Construct a VError, fetching the error message from the libvips
* error buffer.
*/
VError() : _what( vips_error_buffer() ) {}
virtual ~VError() throw() {}
// Extract string
/**
* Get a reference to the underlying C string.
*/
virtual const char *what() const throw() { return _what.c_str(); }
/**
* Print the error message to a stream.
*/
void ostream_print( std::ostream & ) const;
};

File diff suppressed because it is too large Load Diff

View File

@ -34,17 +34,36 @@
VIPS_NAMESPACE_START
class VInterpolate : VObject
/**
* An interpolation. You can pass one of these to something like
* VImage::affine for it to use to interpolate pixels.
*
* The available interpolators vary a bit with your libvips version and how it
* was built, but will include `nearest`, `bilinear` and `bicubic`. Run
* vips -l interpolate` to see them all.
*/
class VInterpolate : public VObject
{
public:
/**
* Create a VInterpolate that wraps a VipsInterpolate object. If steal
* is STEAL, then this VInterpolate takes over ownership of the libvips
* object and will automatically unref it.
*/
VInterpolate( VipsInterpolate *interpolate, VSteal steal = STEAL ) :
VObject( (VipsObject *) interpolate, steal )
{
}
/**
* Create a VInterpolate from a name, for example `"bicubic"`.
*/
static
VInterpolate new_from_name( const char *name, VOption *options = 0 );
/**
* Get a pointer to the underlying VipsInterpolate object.
*/
VipsInterpolate *
get_interpolate() const
{

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
// bodies for vips operations
// Sun 5 Jul 22:36:37 BST 2020
// Mon 17 Aug 18:04:15 BST 2020
// this file is generated automatically, do not edit!
VImage VImage::CMC2LCh( VOption *options ) const