diff --git a/tools/pdbgen/app.pl b/tools/pdbgen/app.pl index 886913588f..4cf86cd8ed 100644 --- a/tools/pdbgen/app.pl +++ b/tools/pdbgen/app.pl @@ -24,21 +24,16 @@ $destdir = "$main::destdir/app"; *arg_ptype = \&Gimp::CodeGen::pdb::arg_ptype; *arg_vname = \&Gimp::CodeGen::pdb::arg_vname; +*enums = \%Gimp::CodeGen::enums::enums; + *write_file = \&Gimp::CodeGen::util::write_file; *FILE_EXT = \$Gimp::CodeGen::util::FILE_EXT; -%testmap = ( - '<' => '>', - '>' => '<', - '<=' => '>=', - '>=' => '<=' -); - sub declare_args { my $proc = shift; my $out = shift; - my $result = ""; + local $result = ""; foreach (@_) { my @args = @{$proc->{$_}} if exists $proc->{$_}; @@ -51,9 +46,10 @@ sub declare_args { } unless (exists $_->{no_declare}) { - my $type = $arg->{type}; - $result .= ' ' x 2 . $type . &arg_vname($_); - $result .= ' = NULL' if exists $_->{init} && $type =~ /\*$/; + $result .= ' ' x 2 . $arg->{type} . &arg_vname($_); + if (!exists $_->{no_init} && exists $_->{init}) { + $result .= $arg->{type} =~ /\*$/ ? ' = NULL' : '0' + } $result .= ";\n"; if (exists $arg->{id_headers}) { @@ -61,13 +57,6 @@ sub declare_args { $out->{headers}->{$_}++; } } - - if (exists $_->{get}) { - my $type = $arg_types{$_->{get}->{type}}->{type}; - $result .= ' ' x 2 . $type . &arg_vname($_->{get}); - $result .= ' = NULL' if $type =~ /\*$/; - $result .= ";\n"; - } } } } @@ -88,17 +77,28 @@ sub make_args { $result .= "\nstatic ProcArg $proc->{name}_${_}[] ="; $result .= "\n{\n"; - foreach my $arg (@{$proc->{$_}}) { - my ($type) = &arg_parse($arg->{type}); - local ($desc) = ""; - - $desc = 'TRUE or FALSE' if $type eq 'boolean'; + foreach $arg (@{$proc->{$_}}) { + my ($type, $name, @remove) = &arg_parse($arg->{type}); + my $desc = $arg->{desc}; + my $info = $arg->{type}; + + for ($type) { + /array/ && do { last }; + /boolean/ && do { $info = 'TRUE or FALSE'; last }; + /int|float/ && do { $info =~ s/$type/$arg->{name}/e; last }; + /enum/ && do { $info = $enums{$name}->{info}; + foreach (@remove) { + $info =~ s/$_ \(.*?\)(, )?// + } last }; + } + + $desc =~ s/%%desc%%/$info/eg; $result .= <{name}, "$arg->{name}", - "@{[ eval qq/"$arg->{desc}"/ ]}" + "$desc" }, CODE } @@ -125,61 +125,81 @@ sub marshal_inargs { my $arg = $arg_types{$pdbtype}; my $type = &arg_ptype($arg); my $var = &arg_vname($_); - + if (exists $arg->{id_func}) { + my $test = exists $_->{on_success} ? '!=' : '=='; + $result .= <{id_func} (args[$argc].value.pdb_$type)) == NULL) - success = FALSE; + if (($var = $arg->{id_func} (args[$argc].value.pdb_$type)) $test NULL) CODE - $result .= <{get}; + $result .= <{on_success}; + $_->{on_success} else - @{[ &arg_vname($_->{get}) ]} = @{[ eval qq/"$arg->{$_->{get}->{type}}"/ ]}; CODE + $result .= ' ' x 4 . "success = FALSE;\n"; $success = 1; } else { - if ($pdbtype eq 'enum') { - # FIXME: implement this + my $code = ' ' x 2 . "$var ="; + + my $cast = ""; + if ($type eq 'pointer' || $arg->{type} =~ /int(16|8)$/) { + $cast = " ($arg->{type})"; } - elsif ($pdbtype eq 'boolean') { - $result .= ' ' x 2 . "$var = "; - $result .= "args[$argc].value.pdb_$type ? TRUE : FALSE;\n"; + $code .= "$cast args[$argc].value.pdb_$type"; + $code .= ' ? TRUE : FALSE' if $pdbtype eq 'boolean'; + $code .= ";\n"; + + if ($pdbtype eq 'string') { + $code .= ' ' x 2 . "success = $var != NULL;\n"; } - else { - my $cast = ""; + elsif (defined $typeinfo[0] || defined $typeinfo[2]) { + my $tests = 0; my $extra = ""; - $cast = " ($arg->{type})" if $type eq "pointer"; - $cast = " ($arg->{type})" if $arg->{type} =~ /int(16|8)$/; + if ($pdbtype eq 'enum') { + my $name = pop @typeinfo; - $result .= ' ' x 2 . "$var ="; - $result .= "$cast args[$argc].value.pdb_$type;\n"; + foreach (@typeinfo) { $extra .= " && $var != $_" } - if ($pdbtype eq 'string') { - $result .= ' ' x 2 . "success = $var != NULL;\n"; - $success = 1; + $typeinfo[0] = $enums{$name}->{start}; + $typeinfo[1] = '>='; + $typeinfo[2] = $enums{$name}->{end}; + $typeinfo[3] = '<='; } - elsif (defined $typeinfo[0] || defined $typeinfo[2]) { - my $tests = 0; - $result .= ' ' x 2 . "success = "; + $code .= ' ' x 2 . "success = "; - if (defined $typeinfo[0]) { - $result .= "$var $testmap{$typeinfo[1]} $typeinfo[0]"; - $tests++; - } - - if (defined $typeinfo[2]) { - $result .= '|| ' if $tests; - $result .= "$var $testmap{$typeinfo[2]} $typeinfo[3]"; - } - - $result .= ";\n"; - - $success = 1; + if (defined $typeinfo[0]) { + $code .= "$var $typeinfo[1] $typeinfo[0]"; + $tests++; } + + if (defined $typeinfo[2]) { + $code .= ' && ' if $tests; + $code .= "$var $typeinfo[3] $typeinfo[2]"; + } + + $code .= "$extra;\n"; } + + if ($code =~ /success/) { + if ($success) { + $code =~ s/^/' ' x 4/meg; + $code =~ s/^ {8}/\t/mg; + + $code .= ' ' x 4 . "}\n"; + $result .= ' ' x 2 . "if (success)\n" . ' ' x 4 . "{\n"; + } + else { + $success_init = 0; + } + + $success = 1; + } + + $result .= $code; } $argc++; $result .= "\n"; @@ -240,7 +260,7 @@ sub generate { my %out; my $total = 0.0; - foreach my $name (@procs) { + foreach $name (@procs) { my $proc = $main::pdb{$name}; my $out = \%{$out{$proc->{group}}}; @@ -248,6 +268,7 @@ sub generate { my @outargs = @{$proc->{outargs}} if exists $proc->{outargs}; local $success = 0; + local $success_init = 1; $out->{pcount}++; $total++; @@ -258,7 +279,7 @@ sub generate { CODE if (exists $proc->{invoke}->{headers}) { - foreach my $header (@{$proc->{invoke}->{headers}}) { + foreach $header (@{$proc->{invoke}->{headers}}) { $out->{headers}->{$header}++; } } @@ -300,8 +321,11 @@ CODE $success = ($code =~ /success =/) unless $success; if ($success) { - $out->{code} .= ' ' x 2; - $out->{code} .= "int success = $proc->{invoke}->{success};\n"; + $success_init = 0 if $proc->{invoke}->{success} eq 'NONE'; + + $out->{code} .= ' ' x 2 . "gboolean success"; + $out->{code} .= " = $proc->{invoke}->{success}" if $success_init; + $out->{code} .= ";\n"; } $out->{code} .= $invoker . $code . "\n"; @@ -376,7 +400,7 @@ HEADER my $cfile = "$destdir/${group}_cmds.c$FILE_EXT"; open CFILE, "> $cfile" or die "Can't open $cmdfile: $!\n"; print CFILE $gpl; - foreach my $header (sort keys %{$out->{headers}}) { + foreach $header (sort keys %{$out->{headers}}) { print CFILE "#include $header\n"; } print CFILE "\n"; diff --git a/tools/pdbgen/enums.pl b/tools/pdbgen/enums.pl new file mode 100644 index 0000000000..3916f68d77 --- /dev/null +++ b/tools/pdbgen/enums.pl @@ -0,0 +1,37 @@ +# The GIMP -- an image manipulation program +# Copyright (C) 1998 Manish Singh + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +package Gimp::CodeGen::enums; + +%enums = ( + ConvertPaletteType => + { name => 'ConvertPaletteType', base => 0, + symbols => [ qw(MAKE_PALETTE REUSE_PALETTE WEB_PALETTE MONO_PALETTE + CUSTOM_PALETTE) ] } + +); + +foreach $enum (values %enums) { + $enum->{start} = $enum->{symbols}->[0]; + $enum->{end} = $enum->{symbols}->[$#{$enum->{symbols}}]; + + my $pos = 0; $enum->{info} = ""; + foreach (@{$enum->{symbols}}) { $enum->{info} .= "$_ ($pos), "; $pos++ } + $enum->{info} =~ s/, $//; +} + +1; diff --git a/tools/pdbgen/lib.pl b/tools/pdbgen/lib.pl index 418a8fa102..daa54556b2 100644 --- a/tools/pdbgen/lib.pl +++ b/tools/pdbgen/lib.pl @@ -36,7 +36,7 @@ sub generate { $type; } - foreach my $name (@procs) { + foreach $name (@procs) { my $proc = $main::pdb{$name}; my $out = \%{$out{$proc->{group}}}; diff --git a/tools/pdbgen/pdb.pl b/tools/pdbgen/pdb.pl index 48d55cd433..b500b4dccc 100644 --- a/tools/pdbgen/pdb.pl +++ b/tools/pdbgen/pdb.pl @@ -33,49 +33,36 @@ package Gimp::CodeGen::pdb; color => { name => 'COLOR' , type => 'guchar *' }, - display => { - name => 'DISPLAY', - type => 'GDisplay *', - id_func => 'gdisplay_get_ID', - id_ret_func => '$var->ID', - id_headers => [ qw("gdisplay.h") ] - }, - image => { - name => 'IMAGE', - type => 'GimpImage *', - id_func => 'pdb_id_to_image', - id_ret_func => 'pdb_image_to_id ($var)', - id_headers => [ qw("procedural_db.h") ] - }, - layer => { - name => 'LAYER', - type => 'GimpLayer *', - id_func => 'layer_get_ID', - id_ret_func => 'drawable_ID (GIMP_DRAWABLE ($var))', - id_headers => [ qw("drawable.h" "layer.h") ] - }, - channel => { - name => 'CHANNEL', - type => 'Channel *', - id_func => 'channel_get_ID', - id_ret_func => 'drawable_ID (GIMP_DRAWABLE ($var))', - id_headers => [ qw("drawable.h" "channel.h") ] - }, - drawable => { - name => 'DRAWABLE', - type => 'GimpDrawable *', - id_func => 'gimp_drawable_get_ID', - id_ret_func => 'drawable_ID (GIMP_DRAWABLE ($var))', - id_headers => [ qw("drawable.h") ], - image => 'drawable_gimage (GIMP_DRAWABLE ($var))' - }, - selection => { - name => 'SELECTION', - type => 'Channel *', - id_func => 'channel_get_ID', - id_ret_func => 'drawable_ID (GIMP_DRAWABLE ($var))', - id_headers => [ qw("drawable.h" "channel.h") ] - }, + display => { name => 'DISPLAY', + type => 'GDisplay *', + id_func => 'gdisplay_get_ID', + id_ret_func => '$var->ID', + id_headers => [ qw("gdisplay.h") ] }, + image => { name => 'IMAGE', + type => 'GimpImage *', + id_func => 'pdb_id_to_image', + id_ret_func => 'pdb_image_to_id ($var)', + id_headers => [ qw("procedural_db.h") ] }, + layer => { name => 'LAYER', + type => 'GimpLayer *', + id_func => 'layer_get_ID', + id_ret_func => 'drawable_ID (GIMP_DRAWABLE ($var))', + id_headers => [ qw("drawable.h" "layer.h") ] }, + channel => { name => 'CHANNEL', + type => 'Channel *', + id_func => 'channel_get_ID', + id_ret_func => 'drawable_ID (GIMP_DRAWABLE ($var))', + id_headers => [ qw("drawable.h" "channel.h") ] }, + drawable => { name => 'DRAWABLE', + type => 'GimpDrawable *', + id_func => 'gimp_drawable_get_ID', + id_ret_func => 'drawable_ID (GIMP_DRAWABLE ($var))', + id_headers => [ qw("drawable.h") ] }, + selection => { name => 'SELECTION', + type => 'Channel *', + id_func => 'channel_get_ID', + id_ret_func => 'drawable_ID (GIMP_DRAWABLE ($var))', + id_headers => [ qw("drawable.h" "channel.h") ] }, boundary => { name => 'BOUNDARY', type => 'gpointer ' }, # ??? FIXME path => { name => 'PATH' , type => 'gpointer ' }, # ??? FIXME @@ -90,12 +77,28 @@ package Gimp::CodeGen::pdb; # Split out the parts of an arg constraint sub arg_parse { + my %testmap = ( + '<' => '>', + '>' => '<', + '<=' => '>=', + '>=' => '<=' + ); + my $arg = shift; - if ($arg =~ /^enum (\w+)/) { - return ('enum', $1); + + if ($arg =~ /^enum (\w+)(.*)/) { + my ($name, $remove) = ($1, $2); + my @retvals = ('enum', $name); + + if ($remove && $remove =~ / \(no /) { + $remove =~ s/ \(no (.*?)\)$/$1/; + push @retvals, split(/,\s*/, $remove); + } + + return @retvals; } - if ($arg =~ /^([\d\.-].*?)? *(<=|<)? *(\w+) *(<=|<)? *([\d\.-].*?)?/) { - return ($3, $1, $2, $5, $4); + elsif ($arg =~ /^([\d\.-].*?)? *(<=|<)? *(\w+) *(<=|<)? *([\d\.-].*?)?/) { + return ($3, $1, $2 ? $testmap{$2} : $2, $5, $4 ? $testmap{$4} : $4); } } diff --git a/tools/pdbgen/pdb/channel_ops.pdb b/tools/pdbgen/pdb/channel_ops.pdb index 492ac79977..dccc4c6b97 100644 --- a/tools/pdbgen/pdb/channel_ops.pdb +++ b/tools/pdbgen/pdb/channel_ops.pdb @@ -35,12 +35,12 @@ HELP @inargs = ( { name => 'drawable', type => 'drawable', - desc => 'The drawable to offset', get => &std_image_arg }, + desc => 'The drawable to offset' }, { name => 'wrap_around', type => 'boolean', desc => 'wrap image around or fill vacated regions' }, { name => 'fill_type', type => 'enum GimpOffsetType', desc => 'fill vacated regions of drawable with background or - transparent: $desc' }, + transparent: %%desc%%' }, { name => 'offset_x', type => 'int32', desc => 'offset by this amount in X direction' }, { name => 'offset_y', type => 'int32', @@ -49,8 +49,12 @@ HELP %invoke = ( headers => [ qw(channel_ops.h) ], + vars => ['GimpImage *gimage'], code => <<'CODE' -offset (gimage, drawable, wrap_around, fill_type, offset_x, offset_y); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + offset (gimage, drawable, wrap_around, fill_type, offset_x, offset_y); +} CODE ); } diff --git a/tools/pdbgen/pdb/convert.pdb b/tools/pdbgen/pdb/convert.pdb index 63026102aa..03487791e4 100644 --- a/tools/pdbgen/pdb/convert.pdb +++ b/tools/pdbgen/pdb/convert.pdb @@ -115,14 +115,14 @@ HELP &std_image_arg, { name => 'dither', type => 'boolean', desc => 'Floyd-Steinberg dithering' }, - { name => 'palette_type', type => 'enum GimpDitherPaletteType', - desc => 'The type of palette to use: $desc' }, + { name => 'palette_type', type => 'enum ConvertPaletteType', + desc => 'The type of palette to use: %%desc%%' }, { name => 'num_cols', type => 'int32', desc => 'the number of colors to quantize to, ignored unless - (palette_type == 0)' }, + (palette_type == MAKE_PALETTE)' }, { name => 'palette', type => 'string', desc => 'The name of the custom palette to use, ignored unless - (palette_type == 4)' } + (palette_type == CUSTOM_PALETTE)' } ); %invoke = ( diff --git a/tools/pdbgen/pdb/drawable.pdb b/tools/pdbgen/pdb/drawable.pdb index f50832e02a..9383285669 100644 --- a/tools/pdbgen/pdb/drawable.pdb +++ b/tools/pdbgen/pdb/drawable.pdb @@ -64,7 +64,7 @@ HELP @inargs = ( &drawable_arg, { name => 'fill_type', type => 'enum GimpFillType', - desc => 'The type of fill: $desc' } + desc => 'The type of fill: %%desc%%' } ); %invoke = ( diff --git a/tools/pdbgen/pdb/edit.pdb b/tools/pdbgen/pdb/edit.pdb index 22ce2bf9ed..1dcbf71f29 100644 --- a/tools/pdbgen/pdb/edit.pdb +++ b/tools/pdbgen/pdb/edit.pdb @@ -21,8 +21,7 @@ sub inargs { @inargs = ( { name => 'drawable', type => 'drawable', - desc => "The drawable to @{[shift]}", - get => &std_image_arg } + desc => "The drawable to @{[shift]}" } ); } @@ -30,7 +29,13 @@ sub inargs { sub invoke { %invoke = ( headers => [ qw("global_edit.h") ], - code => "success = @{[shift]};" + vars => ['GimpImage *gimage'], + code => < [ qw("layer.h" "floating_sel.h") ], code => < 'undo', type => 'boolean', desc => '$desc' }; + push @inargs, { name => 'undo', type => 'boolean', desc => '%%desc%%' }; &invoke; $invoke{code} =~ s/\(floating_sel\);/(floating_sel, undo);/; @@ -139,7 +139,7 @@ HELP &std_pdb_misc; &inargs; - push @inargs, { name => 'undo', type => 'boolean', desc => '$desc' }; + push @inargs, { name => 'undo', type => 'boolean', desc => '%%desc%%' }; &invoke; $invoke{code} =~ s/\(floating_sel\);/(floating_sel, undo);/; diff --git a/tools/pdbgen/pdb/gradient.pdb-21477 b/tools/pdbgen/pdb/gradient.pdb-21477 index aa7a57bbf4..97f294de81 100644 --- a/tools/pdbgen/pdb/gradient.pdb-21477 +++ b/tools/pdbgen/pdb/gradient.pdb-21477 @@ -44,6 +44,7 @@ HELP %invoke = ( headers => [ qw("gradient.h") ], vars => ['gradient_t *grad', 'GSList *list', 'int i = 0'], + success => 'NONE', code => <<'CODE' { gradients = g_new (gchar *, num_gradients); @@ -101,7 +102,6 @@ HELP ); %invoke = ( - success => 'FALSE', headers => [ qw("gradient.h") ], code => 'success = grad_set_grad_to_name (name);' ); diff --git a/tools/pdbgen/pdb/gradient_select.pdb b/tools/pdbgen/pdb/gradient_select.pdb index 75bb7a7db6..21e19b2e0a 100644 --- a/tools/pdbgen/pdb/gradient_select.pdb +++ b/tools/pdbgen/pdb/gradient_select.pdb @@ -40,7 +40,7 @@ HELP { name => 'sample_size', type => '0 < int32 < 10000', desc => 'The size of the sample to return when the gradient is changed $desc', - on_fail => 'G_SAMPLE' } + on_fail => 'sample_size = G_SAMPLE;' } ); @outargs = ( diff --git a/tools/pdbgen/pdb/gradients.pdb b/tools/pdbgen/pdb/gradients.pdb index aa7a57bbf4..97f294de81 100644 --- a/tools/pdbgen/pdb/gradients.pdb +++ b/tools/pdbgen/pdb/gradients.pdb @@ -44,6 +44,7 @@ HELP %invoke = ( headers => [ qw("gradient.h") ], vars => ['gradient_t *grad', 'GSList *list', 'int i = 0'], + success => 'NONE', code => <<'CODE' { gradients = g_new (gchar *, num_gradients); @@ -101,7 +102,6 @@ HELP ); %invoke = ( - success => 'FALSE', headers => [ qw("gradient.h") ], code => 'success = grad_set_grad_to_name (name);' ); diff --git a/tools/pdbgen/pdb/misc_tools.pdb b/tools/pdbgen/pdb/misc_tools.pdb index 8717ab6ab2..9c885c46dd 100644 --- a/tools/pdbgen/pdb/misc_tools.pdb +++ b/tools/pdbgen/pdb/misc_tools.pdb @@ -25,19 +25,37 @@ sub drawable_arg () {{ name => 'drawable', type => 'drawable', desc => 'The affected drawable', - get => &std_image_arg }} +sub drawable_out_arg { + my $type = shift; + my $arg = &drawable_arg; + $arg->{desc} = "The $type drawable"; + $arg; +} + sub sample_merged_arg () {{ name => 'sample_merged', type => 'boolean', desc => 'Use the composite image, not the drawable' }} +sub operation_arg () {{ + name => 'operation', + type => 'enum Selection', + desc => 'The selection operation: %%desc%%' +}} + +sub threshold_arg () {{ + name => 'threshold', + type => '0 <= int32 <= 255', + desc => 'Threshold in intensity levels %%desc%%' +}} + sub antialias_arg () {{ name => 'antialias', type => 'boolean', - desc => 'Antialiasing $desc' + desc => 'Antialiasing (%%desc%%)' }} sub feather_select_args () {( @@ -74,10 +92,9 @@ HELP; @inargs = ( &drawable_arg, { name => 'pressure', type => '0 <= float <= 100', - desc => 'The pressure of the airbrush strokes $desc' }, + desc => 'The pressure of the airbrush strokes (%%desc%%)' }, &stroke_arg ); - delete $inargs[0]->{get}; %invoke = ( headers => [ qw("airbrush.h") ], @@ -102,19 +119,19 @@ HELP @inargs = ( &drawable_arg, { name => 'blend_mode', type => 'enum BlendMode', - desc => 'The type of blend: $desc' }, + desc => 'The type of blend: %%desc%%' }, { name => 'gradient_type', type => 'enum PaintMode', - desc => 'The paint application mode: $desc' }, + desc => 'The paint application mode: %%desc%%' }, { name => 'opacity', type => '0 <= float <= 100', - desc => 'The opacity of the final blend $desc' }, + desc => 'The opacity of the final blend %%desc%%' }, { name => 'offset', type => '0 <= float', desc => 'Offset relates to the starting and ending coordinates specified for the blend. This parameter is mode dependent - $desc' }, + %%desc%%' }, { name => 'repeat', type => 'enum RepeatMode', - desc => 'Repeat mode: $desc' }, + desc => 'Repeat mode: %%desc%%' }, { name => 'supersample', type => 'boolean', - desc => 'Do adaptive supersampling $desc' }, + desc => 'Do adaptive supersampling (%%desc%%)' }, { name => 'max_depth', type => '1 <= int32 <= 9', desc => 'Maximum recursion levels for supersampling', cond => 'supersample' }, @@ -133,9 +150,13 @@ HELP %invoke = ( headers => [ qw("blend.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -blend (gimage, drawable, blend_mode, paint_mode, gradient_type, opacity, - offset, repeat, supersample, max_depth, threshold, x1, y1, x2, y2); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + blend (gimage, drawable, blend_mode, paint_mode, gradient_type, opacity, + offset, repeat, supersample, max_depth, threshold, x1, y1, x2, y2); +} CODE ); } @@ -169,15 +190,15 @@ HELP; %inargs = ( &drawable_arg, { name => 'fill_mode', type => 'enum FillMode', - desc => 'The type of fill: $desc' }, + desc => 'The type of fill: %%desc%%' }, { name => paint_mode, type => 'enum PaintMode', - desc => 'The paint application mode: $desc' }, + desc => 'The paint application mode: %%desc%%' }, { name => opacity, type => '0 <= float <= 100', - desc => 'The opacity of the final bucket fill $desc' }, + desc => 'The opacity of the final bucket fill %%desc%%' }, { name => threshold, type => '0 <= float <= 255', desc => "The threshold determines how extensive the seed fill will be. It's value is specified in terms of intensity levels - \$desc. $validity" }, + %%desc%%. $validity" }, &sample_merged_arg, { name => x, type => 'float', desc => eval qq/{\$a = 'x'; "$coord";}/ }, @@ -187,9 +208,13 @@ HELP; %invoke = ( headers => [ qw ("bucket_fill.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -bucket_fill (gimage, drawable, fill_mode, paint_mode, opacity, threshold, - sample_merged, x, y); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + bucket_fill (gimage, drawable, fill_mode, paint_mode, opacity, + threshold, sample_merged, x, y); +} CODE ); } @@ -220,10 +245,8 @@ HELP &drawable_arg, { name => 'color', type => 'color', desc => 'The color to select' }, - { name => 'threshold', type => '0 <= int32 <= 255', - desc => 'Threshold in intensity levels $desc' }, - { name => 'operation', type => 'enum Operation', - desc => 'The selection operation: $desc' }, + &threshold_arg, + &operation_arg, &antialias_arg, &feather_select_args, &sample_merged_arg @@ -231,9 +254,13 @@ HELP %invoke = ( headers => [ qw("by_color_select.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -by_color_select (gimage, drawable, color, threshold, operation, antialias, - feather, feather_radius, sample_merged); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + by_color_select (gimage, drawable, color, threshold, operation, + antialias, feather, feather_radius, sample_merged); +} CODE ); } @@ -263,20 +290,19 @@ HELP { name => 'src_drawable', type => 'drawable', desc => 'The source drawable' }, { name => 'clone_type', type => 'enum CloneType', - desc => 'The type of clone: $desc' }, + desc => 'The type of clone: %%desc%%' }, { name => 'src_x', type => 'float', desc => 'The x coordinate in the source image' }, { name => 'src_y', type => 'float', desc => 'The y coordinate in the source image' }, &stroke_arg ); - delete $inargs[0]->{get}; %invoke = ( headers => [ qw("clone.h") ], code => <<'CODE' -clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, num_strokes, - strokes); +clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, + num_strokes, strokes); CODE ); } @@ -314,14 +340,18 @@ HELP @outargs = ( { name => 'color', type => 'color', - desc => 'The return color' } + desc => 'The return color', init => 1 } ); %invoke = ( headers => [ qw("color_picker.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' { - if (success = get_color (gimage, drawable, (int) x, (int) y, sample_merged, save_color) + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + if (success = get_color (gimage, drawable, (int) x, (int) y, + sample_merged, save_color) { color = g_new (guchar, 3); color[RED_PIX] = col_value[RED_PIX]; @@ -348,9 +378,9 @@ HELP @inargs = ( &drawable_arg, { name => 'pressure', type => '0 <= float <= 100', - desc => 'The pressure: $desc' }, + desc => 'The pressure: %%desc%%' }, { name => 'convolve_type', type 'enum Convolve (no CUSTOM)', - desc => 'Convolve type: $desc' }, + desc => 'Convolve type: %%desc%%' }, &stroke_arg ); @@ -389,8 +419,7 @@ HELP headers => [ qw("crop.h") ], code => <<'CODE' { - if (new_width > gimage->width || - new_height > gimage->height || + if (new_width > gimage->width || new_height > gimage->height || offx > (gimage->width - new_width) || offy > (gimage->height - new_height) success = FALSE; @@ -422,11 +451,10 @@ HELP { name => 'y', type => 'float', desc => 'y coordinate of upper-left corner of ellipse bounding box' }, { name => 'width', type => '0 < float', - desc => 'The width of the ellipse: $desc' }, + desc => 'The width of the ellipse: %%desc%%' }, { name => 'height', type => '0 < float', - desc => 'The height of the ellipse: $desc' }, - { name => 'operation', 'enum Selection', - desc => 'The selection operation: $desc' }, + desc => 'The height of the ellipse: %%desc%%' }, + &operation_arg, &antialias_arg, &feather_args ); @@ -434,8 +462,8 @@ HELP %invoke = ( headers => [ qw("ellipse_select.h") ], code => <<'CODE' -ellipse_select (gimage, (int) x, (int) y, (int) w, (int) h, op, antialias, - feather, feather_radius); +ellipse_select (gimage, (int) x, (int) y, (int) width, (int) height, + operation, antialias, feather, feather_radius); CODE ); } @@ -457,9 +485,9 @@ HELP &drawable_arg, &stroke_arg, { name => 'hardness', type => 'enum EraserHardness', - desc => '$desc' } + desc => '%%desc%%' } { name => 'method', type => 'enum EraserMethod', - desc => '$desc' } + desc => '%%desc%%' } ); %invoke = ( @@ -492,20 +520,18 @@ HELP @inargs = ( &drawable_arg, { name => 'flip_type', type => 'enum FlipType', - desc => 'Type of flip: $desc' } + desc => 'Type of flip: %%desc%%' } ); - @outargs = ( &drawable_arg ); - $outargs[0]->{alias} = layer; - $outargs[0]->{desc} = 'The flipped drawable'; - $outargs[0]->{no_declare} = 1; - delete $outargs[0]->{get}; + @outargs = ( &drawable_out_arg('flipped') ); %invoke = ( headers => [ qw("flip_tool.h" "tranform_core.h") ], - vars => ['TileManger *float_tiles, *new_tiles', 'Layer *layer'] + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles'], code => <<'CODE' { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + /* Start a transform undo group */ undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); @@ -541,4 +567,626 @@ CODE ); } +sub free_select { + $blurb = 'Create a polygonal selection over the specified image.'; + $help = <<'HELP'; +This tool creates a polygonal selection over the specified image. The polygonal +region can be either added to, subtracted from, or replace the contents of the +previous selection mask. The polygon is specified through an array of floating +point numbers and its length. The length of array must be 2n, where n is the +number of points. Each point is defined by 2 floating point values which +correspond to the x and y coordinates. If the final point does not connect to +the starting point, a connecting segment is automatically added. If the feather +option is enabled, the resulting selection is blurred before combining. The +blur is a gaussian blur with the specified feather radius. +HELP + + &std_pdb_misc; + + @inargs = ( + &std_image_arg, + { name => 'segs', type => 'floatarray', + desc => 'Array of points: { p1.x, p1.y, p2.x, p2.y, ..., + pn.x, pn.y}', + array => { desc => 'Number of points (count 1 coordinate as two + points)' } }, + &operation_arg, + &antialias_arg, + &feather_select_args + ); + + %invoke = ( + headers => qw("free_select.h"), + code => <<'CODE' +free_select (gimage, num_segs, segs, operation, antialias, feather, + feather_radius); +CODE + ); +} + +sub fuzzy_select { + $blurb = <<'BLURB'; +Create a fuzzy selection starting at the specified coordinates on the specified +drawable. +BLURB + + $help = <<'HELP'; +This tool creates a fuzzy selection over the specified image. A fuzzy selection +is determined by a seed fill under the constraints of the specified threshold. +Essentially, the color at the specified coordinates (in the drawable) is +measured and the selection expands outwards from that point to any adjacent +pixels which are not significantly different (as determined by the threshold +value). This process continues until no more expansion is possible. The +antialiasing parameter allows the final selection mask to contain intermediate +values based on close misses to the threshold bar at pixels along the seed fill +boundary. Feathering can be enabled optionally and is controlled with the +"feather_radius" paramter. If the sample_merged parameter is non-zero, the data +of the composite image will be used instead of that for the specified drawable. +This is equivalent to sampling for colors after merging all visible layers. In +the case of a merged sampling, the supplied drawable is ignored. If the sample +is merged, the specified coordinates are relative to the image origin; +otherwise, they are relative to the drawable's origin.' +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'x', type => 'float', + desc => 'x coordinate of initial seed fill point: (image + coordinates)' }, + { name => 'y', type => 'float', + desc => 'y coordinate of initial seed fill point: (image + coordinates)' }, + &threshold_arg, + &operation_arg, + &antialias_arg, + &feather_select_args, + &sample_merged_arg + ); + + %invoke = ( + headers => qw("fuzzy_select.h"), + vars => ['GimpImage *gimage', 'Channel *new, *old_fuzzy_mask'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + new = find_contiguous_region (gimage, drawable, antialias, threshold, + x, y, sample_merged); + old_fuzzy_mask = fuzzy_mask; + fuzzy_mask = new; + + drawable = sample_merged ? NULL : drawable; + fuzzy_select (gimage, drawbale, operation, feather, feather_radius); + + fuzzy_mask = old_fuzzy_mask; +} +CODE + ); +} + +sub paintbrush { + $blurb = 'Paint in the current brush with optional fade out parameter.'; + + $help = <<'HELP'; +This tool is the standard paintbrush. It draws linearly interpolated lines +through the specified stroke coordinates. It operates on the specified drawable +in the foreground color with the active brush. The "fade_out" parameter is +measured in pixels and allows the brush stroke to linearly fall off. The +pressure is set to the maximum at the beginning of the stroke. As the distance +of the stroke nears the fade_out value, the pressure will approach zero. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'fade_out', type => '0 < float', + desc => 'Fade out parameter: %%desc%%' }, + &stroke_arg, + { name => 'method', type => 'enum PaintMethod', + desc => '%%desc%%' } + ); + + %invoke = ( + headers => [ qw("paintbrush.h") ], + code => <<'CODE' +paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, method); +CODE + ); +} + +sub pencil { + $blurb = 'Paint in the current brush without sub-pixel sampling.'; + + $help = <<'HELP'; +This tool is the standard pencil. It draws linearly interpolated lines through +the specified stroke coordinates. It operates on the specified drawable in the +foreground color with the active brush. The brush mask is treated as though it +contains only black and white values. Any value below half is treated as black; +any above half, as white. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + &stroke_arg + ); + + %invoke = ( + headers => qw("fuzzy_select.h"), + code => 'pencil_non_gui (drawable, num_strokes, strokes);' + ); +} + +sub perspective { + $blurb = <<'BLURB'; +Perform a possibly non-affine transformation on the specified drawable. +BLURB + + $help = <<'HELP'; +This tool performs a possibly non-affine transformation on the specified +drawable by allowing the corners of the original bounding box to be arbitrarily +remapped to any values. The specified drawable is remapped if no selection +exists. However, if a selection exists, the portion of the drawable which lies +under the selection is cut from the drawable and made into a floating selection +which is then remapped as specified. The interpolation parameter can be set to +TRUE to indicate that either linear or cubic interpolation should be used to +smooth the resulting remapped drawable. The return value is the ID of the +remapped drawable. If there was no selection, this will be equal to the +drawable ID supplied as input. Otherwise, this will be the newly created and +remapped drawable. The 4 coordinates specify the new locations of each corner +of the original bounding box. By specifying these values, any affine +transformation (rotation, scaling, translation) can be affected. Additionally, +these values can be specified such that the resulting transformed drawable will +appear to have been projected via a perspective transform. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + ); + + my $pos = 0; + foreach $where (qw(upper-left upper-right lower-left lower-right)) { + foreach (qw(x y)) { + push @inargs, + { name => "$_$pos", type => 'float', + desc => "The new $_ coordinate of $where corner of original + bounding box", + alias => "trans_info[@{[ uc $_ ]}$pos]}", no_declare => 1 } + } + $pos++; + } + + @outargs = ( &drawable_out_arg('newly mapped') ); + + %invoke = ( + headers => [ qw("perspective_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'int new_layer', 'double cx, cy', 'double scalex, scaley', + 'double trans_info[8]', 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + /* Determine the perspective transform that maps from + * the unit cube to the trans_info coordinates + */ + perspective_find_transform (trans_info, m); + + cx = float_tiles->x; + cy = float_tiles->y; + scalex = 1.0; + scaley = 1.0; + if (float_tiles->width) + scalex = 1.0 / float_tiles->width; + if (float_tiles->height) + scaley = 1.0 / float_tiles->height; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + gimp_matrix_scale (matrix, scalex, scaley); + gimp_matrix_mult (m, matrix); + + /* Perspective the buffer */ + new_tiles = perspective_tool_perspective (gimage, drawable, NULL, + float_tiles, interpolation, + matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub rect_select { + $blurb = 'Create a rectangular selection over the specified image;'; + + $help = <<'HELP'; +This tool creates a rectangular selection over the specified image. The +rectangular region can be either added to, subtracted from, or replace the +contents of the previous selection mask. If the feather option is enabled, the +resulting selection is blurred before combining. The blur is a gaussian blur +with the specified feather radius. +HELP + + &std_pdb_misc; + + @inargs = ( + &std_image_arg, + { name => 'x', type => 'float', + desc => 'x coordinate of upper-left corner of rectangle' }, + { name => 'y', type => 'float', + desc => 'y coordinate of upper-left corner of rectangle' }, + { name => 'width', type => '0 < float', + desc => 'The width of the rectangle: %%desc%%' } + { name => 'height', type => '0 < float', + desc => 'The height of the rectangle: %%desc%%' } + &operation_arg, + &feather_select_args, + ); + + %invoke = ( + headers => [ qw("rect_select.h") ], + code => <<'CODE' +rect_select (gimage, (int) x, (int) y, (int) width, (int) height, + operation, feather, feather_radius); +CODE + ); +} + +sub rotate_invoker { + $blurb = <<'BLURB'; +Rotate the specified drawable about its center through the specified angle. +BLURB + + $help = <<'HELP'; +This tool rotates the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then rotated by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting rotated drawable. The return value is the ID of the rotated drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and rotated drawable. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + { name => 'angle', type => 'float', + desc => 'The angle of rotation (radians)' } + ); + + @outargs = ( &drawable_arg('rotated') ); + + %invoke = ( + headers => [ qw("rotate_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'Layer *layer', 'int new_layer', 'double cx, cy', + 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + cx = float_tiles->x + float_tiles->width / 2.0; + cy = float_tiles->y + float_tiles->height / 2.0; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + gimp_matrix_rotate (matrix, angle); + gimp_matrix_translate (matrix, +cx, +cy); + + /* Rotate the buffer */ + new_tiles = rotate_tool_rotate (gimage, drawable, NULL, angle, + float_tiles, interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* Push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub scale { + $blurb = 'Scale the specified drawable.'; + + $help = <<'HELP'; +This tool scales the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then scaled by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting scaled drawable. The return value is the ID of the scaled drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and scaled drawable. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + ); + + my $pos = 1; + foreach $where (qw(upper-left lower-right)) { + foreach (qw(x y)) { + push @inargs, + { name => "$_$pos", type => 'float', + desc => "The new $_ coordinate of $where corner of newly + scaled region", + alias => "trans_info[@{[ uc $_ ]}$pos]}", no_declare => 1 } + } + $pos++; + } + + @outargs = ( &drawable_out_arg('scaled') ); + + %invoke = ( + headers => [ qw("scale_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'int new_layer', 'double scalex, scaley', + 'double trans_info[4]', 'GimpMatrix matrix'], + code => <<'CODE' +{ + if (trans_info[X1] < trans_info[X2] && + trans_info[Y1] < trans_info[X2]) + { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + scalex = scaley = 1.0; + if (float_tiles->width) + scalex = (trans_info[X2] - trans_info[X1]) / (double) float_tiles->width +; + if (float_tiles->height) + scaley = (trans_info[Y2] - trans_info[Y1]) / (double) float_tiles->heigh +t; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, float_tiles->x, float_tiles->y); + gimp_matrix_scale (matrix, scalex, scaley); + gimp_matrix_translate (matrix, trans_info[X1], trans_info[Y1]); + + /* Scale the buffer */ + new_tiles = scale_tool_scale (gimage, drawable, NULL, trans_info, + float_tiles, interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* push the undo group end */ + undo_push_group_end (gimage); + } + else + success = FALSE; +} +CODE + ); +} + +sub shear { + $blurb = <<'BLURB'; +Shear the specified drawable about its center by the specified magnitude. +BLURB + + $help = <<'HELP'; +This tool shears the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then sheard by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting sheared drawable. The return value is the ID of the sheard drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and sheard drawable. The shear +type parameter indicates whether the shear will be applied horizontally or +vertically. The magnitude can be either positive or negative and indicates the +extent (in pixels) to shear by. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + { name => 'shear_type', type => 'enum ShearType', + desc => 'Type of shear: %%desc%%' }, + { name => 'magnitude', type => 'float', + desc => 'The magnitude of the shear' } + ); + + @outargs = ( &drawable_arg('sheared') ); + + %invoke = ( + headers => [ qw("perspective_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'Layer *layer', 'int new_layer', 'double cx, cy', + 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + cx = float_tiles->x + float_tiles->width / 2.0; + cy = float_tiles->y + float_tiles->height / 2.0; + + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + /* Shear matrix */ + if (shear_type == HORZ) + gimp_matrix_xshear (matrix, shear_magnitude / float_tiles->height); + else if (shear_type == VERT) + gimp_matrix_yshear (matrix, shear_magnitude / float_tiles->width); + gimp_matrix_translate (matrix, +cx, +cy); + + /* Shear the buffer */ + new_tiles = shear_tool_shear (gimage, drawable, NULL, float_tiles, + interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* Push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub text { + $blurb = <<'BLURB'; +Add text at the specified location as a floating selection or a new layer. +BLURB + + $help = <<'HELP'; +This tool requires font information in the form of nine parameters: size, +foundry, family, weight, slant, set_width, spacing, registry, encoding. The +font size can either be specified in units of pixels or points, and the +appropriate metric is specified using the size_type argument. The x and y +parameters together control the placement of the new text by specifying the +upper left corner of the text bounding box. If the antialias parameter is +non-zero, the generated text will blend more smoothly with underlying layers. +This option requires more time and memory to compute than non-antialiased text; +the resulting floating selection or layer, however, will require the same +amount of memory with or without antialiasing. If the specified drawable +parameter is valid, the text will be created as a floating selection attached +to the drawable. If the drawable parameter is not valid (-1), the text will +appear as a new layer. Finally, a border can be specified around the final +rendered text. The border is measured in pixels. +HELP + + &std_pdb_misc; + $author = 'Martin Edlman'; + $date = '1998'; + + @inargs = ( + &drawable_arg, + { name => 'x', type => 'float', + desc => 'The x coordinate for the left of the text bounding box' }, + { name => 'y', type => 'float', + desc => 'The y coordinate for the top of the text bounding box' }, + { name => 'text', type => 'string', + desc => 'The text to generate', + { name => 'border', type => '-1 <= int32', + desc => 'The size of the border: %%desc%%' } + &antialias_arg, + { name => 'size', type => '0 < float', + desc => 'The size of text in either pixels or points' }, + { name => 'size_type', type => 'enum SizeType', + desc => 'The units of specified size: %%desc%%' } + ); + + foreach (qw(foundry family weight slant set-width spacing registry + encoding)) { + my $var = $_; + $var =~ s/-/_/g; + + push @inargs, { name => $var, type => 'string', + desc => qq/The font $_, "*" for any/ } + } + + @outargs = ( + { name => 'text_layer', type => 'layer', + desc => 'The new text layer' } + ); + + %invoke = ( + headers => [ qw("text_tool.h") ], + vars => ['GimpImage *gimage', 'gchar *fontname[2048]'], + code => <<'CODE' +{ + if (antialias) + size *= SUPERSAMPLE; + + success = text_get_xlfd (size, size_type, foundry, family, weight, + slant, set_width, spacing, registry, encoding, + fontname); + + if (success) + { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + text_layer = text_render (gimage, drawable, x, y, fontname, text, + border, antialias); + success = text_layer != NULL; + } +} +CODE + ); +} diff --git a/tools/pdbgen/pdb/paint_tools.pdb b/tools/pdbgen/pdb/paint_tools.pdb index 8717ab6ab2..9c885c46dd 100644 --- a/tools/pdbgen/pdb/paint_tools.pdb +++ b/tools/pdbgen/pdb/paint_tools.pdb @@ -25,19 +25,37 @@ sub drawable_arg () {{ name => 'drawable', type => 'drawable', desc => 'The affected drawable', - get => &std_image_arg }} +sub drawable_out_arg { + my $type = shift; + my $arg = &drawable_arg; + $arg->{desc} = "The $type drawable"; + $arg; +} + sub sample_merged_arg () {{ name => 'sample_merged', type => 'boolean', desc => 'Use the composite image, not the drawable' }} +sub operation_arg () {{ + name => 'operation', + type => 'enum Selection', + desc => 'The selection operation: %%desc%%' +}} + +sub threshold_arg () {{ + name => 'threshold', + type => '0 <= int32 <= 255', + desc => 'Threshold in intensity levels %%desc%%' +}} + sub antialias_arg () {{ name => 'antialias', type => 'boolean', - desc => 'Antialiasing $desc' + desc => 'Antialiasing (%%desc%%)' }} sub feather_select_args () {( @@ -74,10 +92,9 @@ HELP; @inargs = ( &drawable_arg, { name => 'pressure', type => '0 <= float <= 100', - desc => 'The pressure of the airbrush strokes $desc' }, + desc => 'The pressure of the airbrush strokes (%%desc%%)' }, &stroke_arg ); - delete $inargs[0]->{get}; %invoke = ( headers => [ qw("airbrush.h") ], @@ -102,19 +119,19 @@ HELP @inargs = ( &drawable_arg, { name => 'blend_mode', type => 'enum BlendMode', - desc => 'The type of blend: $desc' }, + desc => 'The type of blend: %%desc%%' }, { name => 'gradient_type', type => 'enum PaintMode', - desc => 'The paint application mode: $desc' }, + desc => 'The paint application mode: %%desc%%' }, { name => 'opacity', type => '0 <= float <= 100', - desc => 'The opacity of the final blend $desc' }, + desc => 'The opacity of the final blend %%desc%%' }, { name => 'offset', type => '0 <= float', desc => 'Offset relates to the starting and ending coordinates specified for the blend. This parameter is mode dependent - $desc' }, + %%desc%%' }, { name => 'repeat', type => 'enum RepeatMode', - desc => 'Repeat mode: $desc' }, + desc => 'Repeat mode: %%desc%%' }, { name => 'supersample', type => 'boolean', - desc => 'Do adaptive supersampling $desc' }, + desc => 'Do adaptive supersampling (%%desc%%)' }, { name => 'max_depth', type => '1 <= int32 <= 9', desc => 'Maximum recursion levels for supersampling', cond => 'supersample' }, @@ -133,9 +150,13 @@ HELP %invoke = ( headers => [ qw("blend.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -blend (gimage, drawable, blend_mode, paint_mode, gradient_type, opacity, - offset, repeat, supersample, max_depth, threshold, x1, y1, x2, y2); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + blend (gimage, drawable, blend_mode, paint_mode, gradient_type, opacity, + offset, repeat, supersample, max_depth, threshold, x1, y1, x2, y2); +} CODE ); } @@ -169,15 +190,15 @@ HELP; %inargs = ( &drawable_arg, { name => 'fill_mode', type => 'enum FillMode', - desc => 'The type of fill: $desc' }, + desc => 'The type of fill: %%desc%%' }, { name => paint_mode, type => 'enum PaintMode', - desc => 'The paint application mode: $desc' }, + desc => 'The paint application mode: %%desc%%' }, { name => opacity, type => '0 <= float <= 100', - desc => 'The opacity of the final bucket fill $desc' }, + desc => 'The opacity of the final bucket fill %%desc%%' }, { name => threshold, type => '0 <= float <= 255', desc => "The threshold determines how extensive the seed fill will be. It's value is specified in terms of intensity levels - \$desc. $validity" }, + %%desc%%. $validity" }, &sample_merged_arg, { name => x, type => 'float', desc => eval qq/{\$a = 'x'; "$coord";}/ }, @@ -187,9 +208,13 @@ HELP; %invoke = ( headers => [ qw ("bucket_fill.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -bucket_fill (gimage, drawable, fill_mode, paint_mode, opacity, threshold, - sample_merged, x, y); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + bucket_fill (gimage, drawable, fill_mode, paint_mode, opacity, + threshold, sample_merged, x, y); +} CODE ); } @@ -220,10 +245,8 @@ HELP &drawable_arg, { name => 'color', type => 'color', desc => 'The color to select' }, - { name => 'threshold', type => '0 <= int32 <= 255', - desc => 'Threshold in intensity levels $desc' }, - { name => 'operation', type => 'enum Operation', - desc => 'The selection operation: $desc' }, + &threshold_arg, + &operation_arg, &antialias_arg, &feather_select_args, &sample_merged_arg @@ -231,9 +254,13 @@ HELP %invoke = ( headers => [ qw("by_color_select.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -by_color_select (gimage, drawable, color, threshold, operation, antialias, - feather, feather_radius, sample_merged); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + by_color_select (gimage, drawable, color, threshold, operation, + antialias, feather, feather_radius, sample_merged); +} CODE ); } @@ -263,20 +290,19 @@ HELP { name => 'src_drawable', type => 'drawable', desc => 'The source drawable' }, { name => 'clone_type', type => 'enum CloneType', - desc => 'The type of clone: $desc' }, + desc => 'The type of clone: %%desc%%' }, { name => 'src_x', type => 'float', desc => 'The x coordinate in the source image' }, { name => 'src_y', type => 'float', desc => 'The y coordinate in the source image' }, &stroke_arg ); - delete $inargs[0]->{get}; %invoke = ( headers => [ qw("clone.h") ], code => <<'CODE' -clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, num_strokes, - strokes); +clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, + num_strokes, strokes); CODE ); } @@ -314,14 +340,18 @@ HELP @outargs = ( { name => 'color', type => 'color', - desc => 'The return color' } + desc => 'The return color', init => 1 } ); %invoke = ( headers => [ qw("color_picker.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' { - if (success = get_color (gimage, drawable, (int) x, (int) y, sample_merged, save_color) + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + if (success = get_color (gimage, drawable, (int) x, (int) y, + sample_merged, save_color) { color = g_new (guchar, 3); color[RED_PIX] = col_value[RED_PIX]; @@ -348,9 +378,9 @@ HELP @inargs = ( &drawable_arg, { name => 'pressure', type => '0 <= float <= 100', - desc => 'The pressure: $desc' }, + desc => 'The pressure: %%desc%%' }, { name => 'convolve_type', type 'enum Convolve (no CUSTOM)', - desc => 'Convolve type: $desc' }, + desc => 'Convolve type: %%desc%%' }, &stroke_arg ); @@ -389,8 +419,7 @@ HELP headers => [ qw("crop.h") ], code => <<'CODE' { - if (new_width > gimage->width || - new_height > gimage->height || + if (new_width > gimage->width || new_height > gimage->height || offx > (gimage->width - new_width) || offy > (gimage->height - new_height) success = FALSE; @@ -422,11 +451,10 @@ HELP { name => 'y', type => 'float', desc => 'y coordinate of upper-left corner of ellipse bounding box' }, { name => 'width', type => '0 < float', - desc => 'The width of the ellipse: $desc' }, + desc => 'The width of the ellipse: %%desc%%' }, { name => 'height', type => '0 < float', - desc => 'The height of the ellipse: $desc' }, - { name => 'operation', 'enum Selection', - desc => 'The selection operation: $desc' }, + desc => 'The height of the ellipse: %%desc%%' }, + &operation_arg, &antialias_arg, &feather_args ); @@ -434,8 +462,8 @@ HELP %invoke = ( headers => [ qw("ellipse_select.h") ], code => <<'CODE' -ellipse_select (gimage, (int) x, (int) y, (int) w, (int) h, op, antialias, - feather, feather_radius); +ellipse_select (gimage, (int) x, (int) y, (int) width, (int) height, + operation, antialias, feather, feather_radius); CODE ); } @@ -457,9 +485,9 @@ HELP &drawable_arg, &stroke_arg, { name => 'hardness', type => 'enum EraserHardness', - desc => '$desc' } + desc => '%%desc%%' } { name => 'method', type => 'enum EraserMethod', - desc => '$desc' } + desc => '%%desc%%' } ); %invoke = ( @@ -492,20 +520,18 @@ HELP @inargs = ( &drawable_arg, { name => 'flip_type', type => 'enum FlipType', - desc => 'Type of flip: $desc' } + desc => 'Type of flip: %%desc%%' } ); - @outargs = ( &drawable_arg ); - $outargs[0]->{alias} = layer; - $outargs[0]->{desc} = 'The flipped drawable'; - $outargs[0]->{no_declare} = 1; - delete $outargs[0]->{get}; + @outargs = ( &drawable_out_arg('flipped') ); %invoke = ( headers => [ qw("flip_tool.h" "tranform_core.h") ], - vars => ['TileManger *float_tiles, *new_tiles', 'Layer *layer'] + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles'], code => <<'CODE' { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + /* Start a transform undo group */ undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); @@ -541,4 +567,626 @@ CODE ); } +sub free_select { + $blurb = 'Create a polygonal selection over the specified image.'; + $help = <<'HELP'; +This tool creates a polygonal selection over the specified image. The polygonal +region can be either added to, subtracted from, or replace the contents of the +previous selection mask. The polygon is specified through an array of floating +point numbers and its length. The length of array must be 2n, where n is the +number of points. Each point is defined by 2 floating point values which +correspond to the x and y coordinates. If the final point does not connect to +the starting point, a connecting segment is automatically added. If the feather +option is enabled, the resulting selection is blurred before combining. The +blur is a gaussian blur with the specified feather radius. +HELP + + &std_pdb_misc; + + @inargs = ( + &std_image_arg, + { name => 'segs', type => 'floatarray', + desc => 'Array of points: { p1.x, p1.y, p2.x, p2.y, ..., + pn.x, pn.y}', + array => { desc => 'Number of points (count 1 coordinate as two + points)' } }, + &operation_arg, + &antialias_arg, + &feather_select_args + ); + + %invoke = ( + headers => qw("free_select.h"), + code => <<'CODE' +free_select (gimage, num_segs, segs, operation, antialias, feather, + feather_radius); +CODE + ); +} + +sub fuzzy_select { + $blurb = <<'BLURB'; +Create a fuzzy selection starting at the specified coordinates on the specified +drawable. +BLURB + + $help = <<'HELP'; +This tool creates a fuzzy selection over the specified image. A fuzzy selection +is determined by a seed fill under the constraints of the specified threshold. +Essentially, the color at the specified coordinates (in the drawable) is +measured and the selection expands outwards from that point to any adjacent +pixels which are not significantly different (as determined by the threshold +value). This process continues until no more expansion is possible. The +antialiasing parameter allows the final selection mask to contain intermediate +values based on close misses to the threshold bar at pixels along the seed fill +boundary. Feathering can be enabled optionally and is controlled with the +"feather_radius" paramter. If the sample_merged parameter is non-zero, the data +of the composite image will be used instead of that for the specified drawable. +This is equivalent to sampling for colors after merging all visible layers. In +the case of a merged sampling, the supplied drawable is ignored. If the sample +is merged, the specified coordinates are relative to the image origin; +otherwise, they are relative to the drawable's origin.' +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'x', type => 'float', + desc => 'x coordinate of initial seed fill point: (image + coordinates)' }, + { name => 'y', type => 'float', + desc => 'y coordinate of initial seed fill point: (image + coordinates)' }, + &threshold_arg, + &operation_arg, + &antialias_arg, + &feather_select_args, + &sample_merged_arg + ); + + %invoke = ( + headers => qw("fuzzy_select.h"), + vars => ['GimpImage *gimage', 'Channel *new, *old_fuzzy_mask'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + new = find_contiguous_region (gimage, drawable, antialias, threshold, + x, y, sample_merged); + old_fuzzy_mask = fuzzy_mask; + fuzzy_mask = new; + + drawable = sample_merged ? NULL : drawable; + fuzzy_select (gimage, drawbale, operation, feather, feather_radius); + + fuzzy_mask = old_fuzzy_mask; +} +CODE + ); +} + +sub paintbrush { + $blurb = 'Paint in the current brush with optional fade out parameter.'; + + $help = <<'HELP'; +This tool is the standard paintbrush. It draws linearly interpolated lines +through the specified stroke coordinates. It operates on the specified drawable +in the foreground color with the active brush. The "fade_out" parameter is +measured in pixels and allows the brush stroke to linearly fall off. The +pressure is set to the maximum at the beginning of the stroke. As the distance +of the stroke nears the fade_out value, the pressure will approach zero. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'fade_out', type => '0 < float', + desc => 'Fade out parameter: %%desc%%' }, + &stroke_arg, + { name => 'method', type => 'enum PaintMethod', + desc => '%%desc%%' } + ); + + %invoke = ( + headers => [ qw("paintbrush.h") ], + code => <<'CODE' +paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, method); +CODE + ); +} + +sub pencil { + $blurb = 'Paint in the current brush without sub-pixel sampling.'; + + $help = <<'HELP'; +This tool is the standard pencil. It draws linearly interpolated lines through +the specified stroke coordinates. It operates on the specified drawable in the +foreground color with the active brush. The brush mask is treated as though it +contains only black and white values. Any value below half is treated as black; +any above half, as white. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + &stroke_arg + ); + + %invoke = ( + headers => qw("fuzzy_select.h"), + code => 'pencil_non_gui (drawable, num_strokes, strokes);' + ); +} + +sub perspective { + $blurb = <<'BLURB'; +Perform a possibly non-affine transformation on the specified drawable. +BLURB + + $help = <<'HELP'; +This tool performs a possibly non-affine transformation on the specified +drawable by allowing the corners of the original bounding box to be arbitrarily +remapped to any values. The specified drawable is remapped if no selection +exists. However, if a selection exists, the portion of the drawable which lies +under the selection is cut from the drawable and made into a floating selection +which is then remapped as specified. The interpolation parameter can be set to +TRUE to indicate that either linear or cubic interpolation should be used to +smooth the resulting remapped drawable. The return value is the ID of the +remapped drawable. If there was no selection, this will be equal to the +drawable ID supplied as input. Otherwise, this will be the newly created and +remapped drawable. The 4 coordinates specify the new locations of each corner +of the original bounding box. By specifying these values, any affine +transformation (rotation, scaling, translation) can be affected. Additionally, +these values can be specified such that the resulting transformed drawable will +appear to have been projected via a perspective transform. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + ); + + my $pos = 0; + foreach $where (qw(upper-left upper-right lower-left lower-right)) { + foreach (qw(x y)) { + push @inargs, + { name => "$_$pos", type => 'float', + desc => "The new $_ coordinate of $where corner of original + bounding box", + alias => "trans_info[@{[ uc $_ ]}$pos]}", no_declare => 1 } + } + $pos++; + } + + @outargs = ( &drawable_out_arg('newly mapped') ); + + %invoke = ( + headers => [ qw("perspective_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'int new_layer', 'double cx, cy', 'double scalex, scaley', + 'double trans_info[8]', 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + /* Determine the perspective transform that maps from + * the unit cube to the trans_info coordinates + */ + perspective_find_transform (trans_info, m); + + cx = float_tiles->x; + cy = float_tiles->y; + scalex = 1.0; + scaley = 1.0; + if (float_tiles->width) + scalex = 1.0 / float_tiles->width; + if (float_tiles->height) + scaley = 1.0 / float_tiles->height; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + gimp_matrix_scale (matrix, scalex, scaley); + gimp_matrix_mult (m, matrix); + + /* Perspective the buffer */ + new_tiles = perspective_tool_perspective (gimage, drawable, NULL, + float_tiles, interpolation, + matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub rect_select { + $blurb = 'Create a rectangular selection over the specified image;'; + + $help = <<'HELP'; +This tool creates a rectangular selection over the specified image. The +rectangular region can be either added to, subtracted from, or replace the +contents of the previous selection mask. If the feather option is enabled, the +resulting selection is blurred before combining. The blur is a gaussian blur +with the specified feather radius. +HELP + + &std_pdb_misc; + + @inargs = ( + &std_image_arg, + { name => 'x', type => 'float', + desc => 'x coordinate of upper-left corner of rectangle' }, + { name => 'y', type => 'float', + desc => 'y coordinate of upper-left corner of rectangle' }, + { name => 'width', type => '0 < float', + desc => 'The width of the rectangle: %%desc%%' } + { name => 'height', type => '0 < float', + desc => 'The height of the rectangle: %%desc%%' } + &operation_arg, + &feather_select_args, + ); + + %invoke = ( + headers => [ qw("rect_select.h") ], + code => <<'CODE' +rect_select (gimage, (int) x, (int) y, (int) width, (int) height, + operation, feather, feather_radius); +CODE + ); +} + +sub rotate_invoker { + $blurb = <<'BLURB'; +Rotate the specified drawable about its center through the specified angle. +BLURB + + $help = <<'HELP'; +This tool rotates the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then rotated by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting rotated drawable. The return value is the ID of the rotated drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and rotated drawable. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + { name => 'angle', type => 'float', + desc => 'The angle of rotation (radians)' } + ); + + @outargs = ( &drawable_arg('rotated') ); + + %invoke = ( + headers => [ qw("rotate_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'Layer *layer', 'int new_layer', 'double cx, cy', + 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + cx = float_tiles->x + float_tiles->width / 2.0; + cy = float_tiles->y + float_tiles->height / 2.0; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + gimp_matrix_rotate (matrix, angle); + gimp_matrix_translate (matrix, +cx, +cy); + + /* Rotate the buffer */ + new_tiles = rotate_tool_rotate (gimage, drawable, NULL, angle, + float_tiles, interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* Push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub scale { + $blurb = 'Scale the specified drawable.'; + + $help = <<'HELP'; +This tool scales the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then scaled by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting scaled drawable. The return value is the ID of the scaled drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and scaled drawable. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + ); + + my $pos = 1; + foreach $where (qw(upper-left lower-right)) { + foreach (qw(x y)) { + push @inargs, + { name => "$_$pos", type => 'float', + desc => "The new $_ coordinate of $where corner of newly + scaled region", + alias => "trans_info[@{[ uc $_ ]}$pos]}", no_declare => 1 } + } + $pos++; + } + + @outargs = ( &drawable_out_arg('scaled') ); + + %invoke = ( + headers => [ qw("scale_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'int new_layer', 'double scalex, scaley', + 'double trans_info[4]', 'GimpMatrix matrix'], + code => <<'CODE' +{ + if (trans_info[X1] < trans_info[X2] && + trans_info[Y1] < trans_info[X2]) + { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + scalex = scaley = 1.0; + if (float_tiles->width) + scalex = (trans_info[X2] - trans_info[X1]) / (double) float_tiles->width +; + if (float_tiles->height) + scaley = (trans_info[Y2] - trans_info[Y1]) / (double) float_tiles->heigh +t; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, float_tiles->x, float_tiles->y); + gimp_matrix_scale (matrix, scalex, scaley); + gimp_matrix_translate (matrix, trans_info[X1], trans_info[Y1]); + + /* Scale the buffer */ + new_tiles = scale_tool_scale (gimage, drawable, NULL, trans_info, + float_tiles, interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* push the undo group end */ + undo_push_group_end (gimage); + } + else + success = FALSE; +} +CODE + ); +} + +sub shear { + $blurb = <<'BLURB'; +Shear the specified drawable about its center by the specified magnitude. +BLURB + + $help = <<'HELP'; +This tool shears the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then sheard by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting sheared drawable. The return value is the ID of the sheard drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and sheard drawable. The shear +type parameter indicates whether the shear will be applied horizontally or +vertically. The magnitude can be either positive or negative and indicates the +extent (in pixels) to shear by. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + { name => 'shear_type', type => 'enum ShearType', + desc => 'Type of shear: %%desc%%' }, + { name => 'magnitude', type => 'float', + desc => 'The magnitude of the shear' } + ); + + @outargs = ( &drawable_arg('sheared') ); + + %invoke = ( + headers => [ qw("perspective_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'Layer *layer', 'int new_layer', 'double cx, cy', + 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + cx = float_tiles->x + float_tiles->width / 2.0; + cy = float_tiles->y + float_tiles->height / 2.0; + + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + /* Shear matrix */ + if (shear_type == HORZ) + gimp_matrix_xshear (matrix, shear_magnitude / float_tiles->height); + else if (shear_type == VERT) + gimp_matrix_yshear (matrix, shear_magnitude / float_tiles->width); + gimp_matrix_translate (matrix, +cx, +cy); + + /* Shear the buffer */ + new_tiles = shear_tool_shear (gimage, drawable, NULL, float_tiles, + interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* Push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub text { + $blurb = <<'BLURB'; +Add text at the specified location as a floating selection or a new layer. +BLURB + + $help = <<'HELP'; +This tool requires font information in the form of nine parameters: size, +foundry, family, weight, slant, set_width, spacing, registry, encoding. The +font size can either be specified in units of pixels or points, and the +appropriate metric is specified using the size_type argument. The x and y +parameters together control the placement of the new text by specifying the +upper left corner of the text bounding box. If the antialias parameter is +non-zero, the generated text will blend more smoothly with underlying layers. +This option requires more time and memory to compute than non-antialiased text; +the resulting floating selection or layer, however, will require the same +amount of memory with or without antialiasing. If the specified drawable +parameter is valid, the text will be created as a floating selection attached +to the drawable. If the drawable parameter is not valid (-1), the text will +appear as a new layer. Finally, a border can be specified around the final +rendered text. The border is measured in pixels. +HELP + + &std_pdb_misc; + $author = 'Martin Edlman'; + $date = '1998'; + + @inargs = ( + &drawable_arg, + { name => 'x', type => 'float', + desc => 'The x coordinate for the left of the text bounding box' }, + { name => 'y', type => 'float', + desc => 'The y coordinate for the top of the text bounding box' }, + { name => 'text', type => 'string', + desc => 'The text to generate', + { name => 'border', type => '-1 <= int32', + desc => 'The size of the border: %%desc%%' } + &antialias_arg, + { name => 'size', type => '0 < float', + desc => 'The size of text in either pixels or points' }, + { name => 'size_type', type => 'enum SizeType', + desc => 'The units of specified size: %%desc%%' } + ); + + foreach (qw(foundry family weight slant set-width spacing registry + encoding)) { + my $var = $_; + $var =~ s/-/_/g; + + push @inargs, { name => $var, type => 'string', + desc => qq/The font $_, "*" for any/ } + } + + @outargs = ( + { name => 'text_layer', type => 'layer', + desc => 'The new text layer' } + ); + + %invoke = ( + headers => [ qw("text_tool.h") ], + vars => ['GimpImage *gimage', 'gchar *fontname[2048]'], + code => <<'CODE' +{ + if (antialias) + size *= SUPERSAMPLE; + + success = text_get_xlfd (size, size_type, foundry, family, weight, + slant, set_width, spacing, registry, encoding, + fontname); + + if (success) + { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + text_layer = text_render (gimage, drawable, x, y, fontname, text, + border, antialias); + success = text_layer != NULL; + } +} +CODE + ); +} diff --git a/tools/pdbgen/pdb/procedural_db.pdb b/tools/pdbgen/pdb/procedural_db.pdb index 0b2487bf72..a4096c5a76 100644 --- a/tools/pdbgen/pdb/procedural_db.pdb +++ b/tools/pdbgen/pdb/procedural_db.pdb @@ -67,7 +67,7 @@ HELP @outargs = ( { name => "${type}_type", type => 'enum PDBArgType', - desc => "The type of $long_type \$desc", + desc => "The type of $long_type %%desc%%", alias => "${type}->arg_type" }, { name => "${type}_name", type => 'string', desc => "The name of the $long_type", @@ -205,7 +205,7 @@ HELP { name => 'date', type => 'string', desc => 'Copyright date' }, { name => 'proc_type', type => 'enum PDBProcType', - desc => 'The procedure type: $desc' }, + desc => 'The procedure type: %%desc%%' }, { name => 'num_args', type => 'int32', desc => 'The number of input arguments' }, { name => 'num_values', type => 'int32', diff --git a/tools/pdbgen/pdb/tools.pdb b/tools/pdbgen/pdb/tools.pdb index 8717ab6ab2..9c885c46dd 100644 --- a/tools/pdbgen/pdb/tools.pdb +++ b/tools/pdbgen/pdb/tools.pdb @@ -25,19 +25,37 @@ sub drawable_arg () {{ name => 'drawable', type => 'drawable', desc => 'The affected drawable', - get => &std_image_arg }} +sub drawable_out_arg { + my $type = shift; + my $arg = &drawable_arg; + $arg->{desc} = "The $type drawable"; + $arg; +} + sub sample_merged_arg () {{ name => 'sample_merged', type => 'boolean', desc => 'Use the composite image, not the drawable' }} +sub operation_arg () {{ + name => 'operation', + type => 'enum Selection', + desc => 'The selection operation: %%desc%%' +}} + +sub threshold_arg () {{ + name => 'threshold', + type => '0 <= int32 <= 255', + desc => 'Threshold in intensity levels %%desc%%' +}} + sub antialias_arg () {{ name => 'antialias', type => 'boolean', - desc => 'Antialiasing $desc' + desc => 'Antialiasing (%%desc%%)' }} sub feather_select_args () {( @@ -74,10 +92,9 @@ HELP; @inargs = ( &drawable_arg, { name => 'pressure', type => '0 <= float <= 100', - desc => 'The pressure of the airbrush strokes $desc' }, + desc => 'The pressure of the airbrush strokes (%%desc%%)' }, &stroke_arg ); - delete $inargs[0]->{get}; %invoke = ( headers => [ qw("airbrush.h") ], @@ -102,19 +119,19 @@ HELP @inargs = ( &drawable_arg, { name => 'blend_mode', type => 'enum BlendMode', - desc => 'The type of blend: $desc' }, + desc => 'The type of blend: %%desc%%' }, { name => 'gradient_type', type => 'enum PaintMode', - desc => 'The paint application mode: $desc' }, + desc => 'The paint application mode: %%desc%%' }, { name => 'opacity', type => '0 <= float <= 100', - desc => 'The opacity of the final blend $desc' }, + desc => 'The opacity of the final blend %%desc%%' }, { name => 'offset', type => '0 <= float', desc => 'Offset relates to the starting and ending coordinates specified for the blend. This parameter is mode dependent - $desc' }, + %%desc%%' }, { name => 'repeat', type => 'enum RepeatMode', - desc => 'Repeat mode: $desc' }, + desc => 'Repeat mode: %%desc%%' }, { name => 'supersample', type => 'boolean', - desc => 'Do adaptive supersampling $desc' }, + desc => 'Do adaptive supersampling (%%desc%%)' }, { name => 'max_depth', type => '1 <= int32 <= 9', desc => 'Maximum recursion levels for supersampling', cond => 'supersample' }, @@ -133,9 +150,13 @@ HELP %invoke = ( headers => [ qw("blend.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -blend (gimage, drawable, blend_mode, paint_mode, gradient_type, opacity, - offset, repeat, supersample, max_depth, threshold, x1, y1, x2, y2); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + blend (gimage, drawable, blend_mode, paint_mode, gradient_type, opacity, + offset, repeat, supersample, max_depth, threshold, x1, y1, x2, y2); +} CODE ); } @@ -169,15 +190,15 @@ HELP; %inargs = ( &drawable_arg, { name => 'fill_mode', type => 'enum FillMode', - desc => 'The type of fill: $desc' }, + desc => 'The type of fill: %%desc%%' }, { name => paint_mode, type => 'enum PaintMode', - desc => 'The paint application mode: $desc' }, + desc => 'The paint application mode: %%desc%%' }, { name => opacity, type => '0 <= float <= 100', - desc => 'The opacity of the final bucket fill $desc' }, + desc => 'The opacity of the final bucket fill %%desc%%' }, { name => threshold, type => '0 <= float <= 255', desc => "The threshold determines how extensive the seed fill will be. It's value is specified in terms of intensity levels - \$desc. $validity" }, + %%desc%%. $validity" }, &sample_merged_arg, { name => x, type => 'float', desc => eval qq/{\$a = 'x'; "$coord";}/ }, @@ -187,9 +208,13 @@ HELP; %invoke = ( headers => [ qw ("bucket_fill.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -bucket_fill (gimage, drawable, fill_mode, paint_mode, opacity, threshold, - sample_merged, x, y); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + bucket_fill (gimage, drawable, fill_mode, paint_mode, opacity, + threshold, sample_merged, x, y); +} CODE ); } @@ -220,10 +245,8 @@ HELP &drawable_arg, { name => 'color', type => 'color', desc => 'The color to select' }, - { name => 'threshold', type => '0 <= int32 <= 255', - desc => 'Threshold in intensity levels $desc' }, - { name => 'operation', type => 'enum Operation', - desc => 'The selection operation: $desc' }, + &threshold_arg, + &operation_arg, &antialias_arg, &feather_select_args, &sample_merged_arg @@ -231,9 +254,13 @@ HELP %invoke = ( headers => [ qw("by_color_select.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -by_color_select (gimage, drawable, color, threshold, operation, antialias, - feather, feather_radius, sample_merged); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + by_color_select (gimage, drawable, color, threshold, operation, + antialias, feather, feather_radius, sample_merged); +} CODE ); } @@ -263,20 +290,19 @@ HELP { name => 'src_drawable', type => 'drawable', desc => 'The source drawable' }, { name => 'clone_type', type => 'enum CloneType', - desc => 'The type of clone: $desc' }, + desc => 'The type of clone: %%desc%%' }, { name => 'src_x', type => 'float', desc => 'The x coordinate in the source image' }, { name => 'src_y', type => 'float', desc => 'The y coordinate in the source image' }, &stroke_arg ); - delete $inargs[0]->{get}; %invoke = ( headers => [ qw("clone.h") ], code => <<'CODE' -clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, num_strokes, - strokes); +clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, + num_strokes, strokes); CODE ); } @@ -314,14 +340,18 @@ HELP @outargs = ( { name => 'color', type => 'color', - desc => 'The return color' } + desc => 'The return color', init => 1 } ); %invoke = ( headers => [ qw("color_picker.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' { - if (success = get_color (gimage, drawable, (int) x, (int) y, sample_merged, save_color) + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + if (success = get_color (gimage, drawable, (int) x, (int) y, + sample_merged, save_color) { color = g_new (guchar, 3); color[RED_PIX] = col_value[RED_PIX]; @@ -348,9 +378,9 @@ HELP @inargs = ( &drawable_arg, { name => 'pressure', type => '0 <= float <= 100', - desc => 'The pressure: $desc' }, + desc => 'The pressure: %%desc%%' }, { name => 'convolve_type', type 'enum Convolve (no CUSTOM)', - desc => 'Convolve type: $desc' }, + desc => 'Convolve type: %%desc%%' }, &stroke_arg ); @@ -389,8 +419,7 @@ HELP headers => [ qw("crop.h") ], code => <<'CODE' { - if (new_width > gimage->width || - new_height > gimage->height || + if (new_width > gimage->width || new_height > gimage->height || offx > (gimage->width - new_width) || offy > (gimage->height - new_height) success = FALSE; @@ -422,11 +451,10 @@ HELP { name => 'y', type => 'float', desc => 'y coordinate of upper-left corner of ellipse bounding box' }, { name => 'width', type => '0 < float', - desc => 'The width of the ellipse: $desc' }, + desc => 'The width of the ellipse: %%desc%%' }, { name => 'height', type => '0 < float', - desc => 'The height of the ellipse: $desc' }, - { name => 'operation', 'enum Selection', - desc => 'The selection operation: $desc' }, + desc => 'The height of the ellipse: %%desc%%' }, + &operation_arg, &antialias_arg, &feather_args ); @@ -434,8 +462,8 @@ HELP %invoke = ( headers => [ qw("ellipse_select.h") ], code => <<'CODE' -ellipse_select (gimage, (int) x, (int) y, (int) w, (int) h, op, antialias, - feather, feather_radius); +ellipse_select (gimage, (int) x, (int) y, (int) width, (int) height, + operation, antialias, feather, feather_radius); CODE ); } @@ -457,9 +485,9 @@ HELP &drawable_arg, &stroke_arg, { name => 'hardness', type => 'enum EraserHardness', - desc => '$desc' } + desc => '%%desc%%' } { name => 'method', type => 'enum EraserMethod', - desc => '$desc' } + desc => '%%desc%%' } ); %invoke = ( @@ -492,20 +520,18 @@ HELP @inargs = ( &drawable_arg, { name => 'flip_type', type => 'enum FlipType', - desc => 'Type of flip: $desc' } + desc => 'Type of flip: %%desc%%' } ); - @outargs = ( &drawable_arg ); - $outargs[0]->{alias} = layer; - $outargs[0]->{desc} = 'The flipped drawable'; - $outargs[0]->{no_declare} = 1; - delete $outargs[0]->{get}; + @outargs = ( &drawable_out_arg('flipped') ); %invoke = ( headers => [ qw("flip_tool.h" "tranform_core.h") ], - vars => ['TileManger *float_tiles, *new_tiles', 'Layer *layer'] + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles'], code => <<'CODE' { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + /* Start a transform undo group */ undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); @@ -541,4 +567,626 @@ CODE ); } +sub free_select { + $blurb = 'Create a polygonal selection over the specified image.'; + $help = <<'HELP'; +This tool creates a polygonal selection over the specified image. The polygonal +region can be either added to, subtracted from, or replace the contents of the +previous selection mask. The polygon is specified through an array of floating +point numbers and its length. The length of array must be 2n, where n is the +number of points. Each point is defined by 2 floating point values which +correspond to the x and y coordinates. If the final point does not connect to +the starting point, a connecting segment is automatically added. If the feather +option is enabled, the resulting selection is blurred before combining. The +blur is a gaussian blur with the specified feather radius. +HELP + + &std_pdb_misc; + + @inargs = ( + &std_image_arg, + { name => 'segs', type => 'floatarray', + desc => 'Array of points: { p1.x, p1.y, p2.x, p2.y, ..., + pn.x, pn.y}', + array => { desc => 'Number of points (count 1 coordinate as two + points)' } }, + &operation_arg, + &antialias_arg, + &feather_select_args + ); + + %invoke = ( + headers => qw("free_select.h"), + code => <<'CODE' +free_select (gimage, num_segs, segs, operation, antialias, feather, + feather_radius); +CODE + ); +} + +sub fuzzy_select { + $blurb = <<'BLURB'; +Create a fuzzy selection starting at the specified coordinates on the specified +drawable. +BLURB + + $help = <<'HELP'; +This tool creates a fuzzy selection over the specified image. A fuzzy selection +is determined by a seed fill under the constraints of the specified threshold. +Essentially, the color at the specified coordinates (in the drawable) is +measured and the selection expands outwards from that point to any adjacent +pixels which are not significantly different (as determined by the threshold +value). This process continues until no more expansion is possible. The +antialiasing parameter allows the final selection mask to contain intermediate +values based on close misses to the threshold bar at pixels along the seed fill +boundary. Feathering can be enabled optionally and is controlled with the +"feather_radius" paramter. If the sample_merged parameter is non-zero, the data +of the composite image will be used instead of that for the specified drawable. +This is equivalent to sampling for colors after merging all visible layers. In +the case of a merged sampling, the supplied drawable is ignored. If the sample +is merged, the specified coordinates are relative to the image origin; +otherwise, they are relative to the drawable's origin.' +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'x', type => 'float', + desc => 'x coordinate of initial seed fill point: (image + coordinates)' }, + { name => 'y', type => 'float', + desc => 'y coordinate of initial seed fill point: (image + coordinates)' }, + &threshold_arg, + &operation_arg, + &antialias_arg, + &feather_select_args, + &sample_merged_arg + ); + + %invoke = ( + headers => qw("fuzzy_select.h"), + vars => ['GimpImage *gimage', 'Channel *new, *old_fuzzy_mask'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + new = find_contiguous_region (gimage, drawable, antialias, threshold, + x, y, sample_merged); + old_fuzzy_mask = fuzzy_mask; + fuzzy_mask = new; + + drawable = sample_merged ? NULL : drawable; + fuzzy_select (gimage, drawbale, operation, feather, feather_radius); + + fuzzy_mask = old_fuzzy_mask; +} +CODE + ); +} + +sub paintbrush { + $blurb = 'Paint in the current brush with optional fade out parameter.'; + + $help = <<'HELP'; +This tool is the standard paintbrush. It draws linearly interpolated lines +through the specified stroke coordinates. It operates on the specified drawable +in the foreground color with the active brush. The "fade_out" parameter is +measured in pixels and allows the brush stroke to linearly fall off. The +pressure is set to the maximum at the beginning of the stroke. As the distance +of the stroke nears the fade_out value, the pressure will approach zero. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'fade_out', type => '0 < float', + desc => 'Fade out parameter: %%desc%%' }, + &stroke_arg, + { name => 'method', type => 'enum PaintMethod', + desc => '%%desc%%' } + ); + + %invoke = ( + headers => [ qw("paintbrush.h") ], + code => <<'CODE' +paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, method); +CODE + ); +} + +sub pencil { + $blurb = 'Paint in the current brush without sub-pixel sampling.'; + + $help = <<'HELP'; +This tool is the standard pencil. It draws linearly interpolated lines through +the specified stroke coordinates. It operates on the specified drawable in the +foreground color with the active brush. The brush mask is treated as though it +contains only black and white values. Any value below half is treated as black; +any above half, as white. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + &stroke_arg + ); + + %invoke = ( + headers => qw("fuzzy_select.h"), + code => 'pencil_non_gui (drawable, num_strokes, strokes);' + ); +} + +sub perspective { + $blurb = <<'BLURB'; +Perform a possibly non-affine transformation on the specified drawable. +BLURB + + $help = <<'HELP'; +This tool performs a possibly non-affine transformation on the specified +drawable by allowing the corners of the original bounding box to be arbitrarily +remapped to any values. The specified drawable is remapped if no selection +exists. However, if a selection exists, the portion of the drawable which lies +under the selection is cut from the drawable and made into a floating selection +which is then remapped as specified. The interpolation parameter can be set to +TRUE to indicate that either linear or cubic interpolation should be used to +smooth the resulting remapped drawable. The return value is the ID of the +remapped drawable. If there was no selection, this will be equal to the +drawable ID supplied as input. Otherwise, this will be the newly created and +remapped drawable. The 4 coordinates specify the new locations of each corner +of the original bounding box. By specifying these values, any affine +transformation (rotation, scaling, translation) can be affected. Additionally, +these values can be specified such that the resulting transformed drawable will +appear to have been projected via a perspective transform. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + ); + + my $pos = 0; + foreach $where (qw(upper-left upper-right lower-left lower-right)) { + foreach (qw(x y)) { + push @inargs, + { name => "$_$pos", type => 'float', + desc => "The new $_ coordinate of $where corner of original + bounding box", + alias => "trans_info[@{[ uc $_ ]}$pos]}", no_declare => 1 } + } + $pos++; + } + + @outargs = ( &drawable_out_arg('newly mapped') ); + + %invoke = ( + headers => [ qw("perspective_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'int new_layer', 'double cx, cy', 'double scalex, scaley', + 'double trans_info[8]', 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + /* Determine the perspective transform that maps from + * the unit cube to the trans_info coordinates + */ + perspective_find_transform (trans_info, m); + + cx = float_tiles->x; + cy = float_tiles->y; + scalex = 1.0; + scaley = 1.0; + if (float_tiles->width) + scalex = 1.0 / float_tiles->width; + if (float_tiles->height) + scaley = 1.0 / float_tiles->height; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + gimp_matrix_scale (matrix, scalex, scaley); + gimp_matrix_mult (m, matrix); + + /* Perspective the buffer */ + new_tiles = perspective_tool_perspective (gimage, drawable, NULL, + float_tiles, interpolation, + matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub rect_select { + $blurb = 'Create a rectangular selection over the specified image;'; + + $help = <<'HELP'; +This tool creates a rectangular selection over the specified image. The +rectangular region can be either added to, subtracted from, or replace the +contents of the previous selection mask. If the feather option is enabled, the +resulting selection is blurred before combining. The blur is a gaussian blur +with the specified feather radius. +HELP + + &std_pdb_misc; + + @inargs = ( + &std_image_arg, + { name => 'x', type => 'float', + desc => 'x coordinate of upper-left corner of rectangle' }, + { name => 'y', type => 'float', + desc => 'y coordinate of upper-left corner of rectangle' }, + { name => 'width', type => '0 < float', + desc => 'The width of the rectangle: %%desc%%' } + { name => 'height', type => '0 < float', + desc => 'The height of the rectangle: %%desc%%' } + &operation_arg, + &feather_select_args, + ); + + %invoke = ( + headers => [ qw("rect_select.h") ], + code => <<'CODE' +rect_select (gimage, (int) x, (int) y, (int) width, (int) height, + operation, feather, feather_radius); +CODE + ); +} + +sub rotate_invoker { + $blurb = <<'BLURB'; +Rotate the specified drawable about its center through the specified angle. +BLURB + + $help = <<'HELP'; +This tool rotates the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then rotated by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting rotated drawable. The return value is the ID of the rotated drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and rotated drawable. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + { name => 'angle', type => 'float', + desc => 'The angle of rotation (radians)' } + ); + + @outargs = ( &drawable_arg('rotated') ); + + %invoke = ( + headers => [ qw("rotate_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'Layer *layer', 'int new_layer', 'double cx, cy', + 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + cx = float_tiles->x + float_tiles->width / 2.0; + cy = float_tiles->y + float_tiles->height / 2.0; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + gimp_matrix_rotate (matrix, angle); + gimp_matrix_translate (matrix, +cx, +cy); + + /* Rotate the buffer */ + new_tiles = rotate_tool_rotate (gimage, drawable, NULL, angle, + float_tiles, interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* Push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub scale { + $blurb = 'Scale the specified drawable.'; + + $help = <<'HELP'; +This tool scales the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then scaled by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting scaled drawable. The return value is the ID of the scaled drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and scaled drawable. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + ); + + my $pos = 1; + foreach $where (qw(upper-left lower-right)) { + foreach (qw(x y)) { + push @inargs, + { name => "$_$pos", type => 'float', + desc => "The new $_ coordinate of $where corner of newly + scaled region", + alias => "trans_info[@{[ uc $_ ]}$pos]}", no_declare => 1 } + } + $pos++; + } + + @outargs = ( &drawable_out_arg('scaled') ); + + %invoke = ( + headers => [ qw("scale_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'int new_layer', 'double scalex, scaley', + 'double trans_info[4]', 'GimpMatrix matrix'], + code => <<'CODE' +{ + if (trans_info[X1] < trans_info[X2] && + trans_info[Y1] < trans_info[X2]) + { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + scalex = scaley = 1.0; + if (float_tiles->width) + scalex = (trans_info[X2] - trans_info[X1]) / (double) float_tiles->width +; + if (float_tiles->height) + scaley = (trans_info[Y2] - trans_info[Y1]) / (double) float_tiles->heigh +t; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, float_tiles->x, float_tiles->y); + gimp_matrix_scale (matrix, scalex, scaley); + gimp_matrix_translate (matrix, trans_info[X1], trans_info[Y1]); + + /* Scale the buffer */ + new_tiles = scale_tool_scale (gimage, drawable, NULL, trans_info, + float_tiles, interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* push the undo group end */ + undo_push_group_end (gimage); + } + else + success = FALSE; +} +CODE + ); +} + +sub shear { + $blurb = <<'BLURB'; +Shear the specified drawable about its center by the specified magnitude. +BLURB + + $help = <<'HELP'; +This tool shears the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then sheard by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting sheared drawable. The return value is the ID of the sheard drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and sheard drawable. The shear +type parameter indicates whether the shear will be applied horizontally or +vertically. The magnitude can be either positive or negative and indicates the +extent (in pixels) to shear by. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + { name => 'shear_type', type => 'enum ShearType', + desc => 'Type of shear: %%desc%%' }, + { name => 'magnitude', type => 'float', + desc => 'The magnitude of the shear' } + ); + + @outargs = ( &drawable_arg('sheared') ); + + %invoke = ( + headers => [ qw("perspective_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'Layer *layer', 'int new_layer', 'double cx, cy', + 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + cx = float_tiles->x + float_tiles->width / 2.0; + cy = float_tiles->y + float_tiles->height / 2.0; + + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + /* Shear matrix */ + if (shear_type == HORZ) + gimp_matrix_xshear (matrix, shear_magnitude / float_tiles->height); + else if (shear_type == VERT) + gimp_matrix_yshear (matrix, shear_magnitude / float_tiles->width); + gimp_matrix_translate (matrix, +cx, +cy); + + /* Shear the buffer */ + new_tiles = shear_tool_shear (gimage, drawable, NULL, float_tiles, + interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* Push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub text { + $blurb = <<'BLURB'; +Add text at the specified location as a floating selection or a new layer. +BLURB + + $help = <<'HELP'; +This tool requires font information in the form of nine parameters: size, +foundry, family, weight, slant, set_width, spacing, registry, encoding. The +font size can either be specified in units of pixels or points, and the +appropriate metric is specified using the size_type argument. The x and y +parameters together control the placement of the new text by specifying the +upper left corner of the text bounding box. If the antialias parameter is +non-zero, the generated text will blend more smoothly with underlying layers. +This option requires more time and memory to compute than non-antialiased text; +the resulting floating selection or layer, however, will require the same +amount of memory with or without antialiasing. If the specified drawable +parameter is valid, the text will be created as a floating selection attached +to the drawable. If the drawable parameter is not valid (-1), the text will +appear as a new layer. Finally, a border can be specified around the final +rendered text. The border is measured in pixels. +HELP + + &std_pdb_misc; + $author = 'Martin Edlman'; + $date = '1998'; + + @inargs = ( + &drawable_arg, + { name => 'x', type => 'float', + desc => 'The x coordinate for the left of the text bounding box' }, + { name => 'y', type => 'float', + desc => 'The y coordinate for the top of the text bounding box' }, + { name => 'text', type => 'string', + desc => 'The text to generate', + { name => 'border', type => '-1 <= int32', + desc => 'The size of the border: %%desc%%' } + &antialias_arg, + { name => 'size', type => '0 < float', + desc => 'The size of text in either pixels or points' }, + { name => 'size_type', type => 'enum SizeType', + desc => 'The units of specified size: %%desc%%' } + ); + + foreach (qw(foundry family weight slant set-width spacing registry + encoding)) { + my $var = $_; + $var =~ s/-/_/g; + + push @inargs, { name => $var, type => 'string', + desc => qq/The font $_, "*" for any/ } + } + + @outargs = ( + { name => 'text_layer', type => 'layer', + desc => 'The new text layer' } + ); + + %invoke = ( + headers => [ qw("text_tool.h") ], + vars => ['GimpImage *gimage', 'gchar *fontname[2048]'], + code => <<'CODE' +{ + if (antialias) + size *= SUPERSAMPLE; + + success = text_get_xlfd (size, size_type, foundry, family, weight, + slant, set_width, spacing, registry, encoding, + fontname); + + if (success) + { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + text_layer = text_render (gimage, drawable, x, y, fontname, text, + border, antialias); + success = text_layer != NULL; + } +} +CODE + ); +} diff --git a/tools/pdbgen/pdb/transform_tools.pdb b/tools/pdbgen/pdb/transform_tools.pdb index 8717ab6ab2..9c885c46dd 100644 --- a/tools/pdbgen/pdb/transform_tools.pdb +++ b/tools/pdbgen/pdb/transform_tools.pdb @@ -25,19 +25,37 @@ sub drawable_arg () {{ name => 'drawable', type => 'drawable', desc => 'The affected drawable', - get => &std_image_arg }} +sub drawable_out_arg { + my $type = shift; + my $arg = &drawable_arg; + $arg->{desc} = "The $type drawable"; + $arg; +} + sub sample_merged_arg () {{ name => 'sample_merged', type => 'boolean', desc => 'Use the composite image, not the drawable' }} +sub operation_arg () {{ + name => 'operation', + type => 'enum Selection', + desc => 'The selection operation: %%desc%%' +}} + +sub threshold_arg () {{ + name => 'threshold', + type => '0 <= int32 <= 255', + desc => 'Threshold in intensity levels %%desc%%' +}} + sub antialias_arg () {{ name => 'antialias', type => 'boolean', - desc => 'Antialiasing $desc' + desc => 'Antialiasing (%%desc%%)' }} sub feather_select_args () {( @@ -74,10 +92,9 @@ HELP; @inargs = ( &drawable_arg, { name => 'pressure', type => '0 <= float <= 100', - desc => 'The pressure of the airbrush strokes $desc' }, + desc => 'The pressure of the airbrush strokes (%%desc%%)' }, &stroke_arg ); - delete $inargs[0]->{get}; %invoke = ( headers => [ qw("airbrush.h") ], @@ -102,19 +119,19 @@ HELP @inargs = ( &drawable_arg, { name => 'blend_mode', type => 'enum BlendMode', - desc => 'The type of blend: $desc' }, + desc => 'The type of blend: %%desc%%' }, { name => 'gradient_type', type => 'enum PaintMode', - desc => 'The paint application mode: $desc' }, + desc => 'The paint application mode: %%desc%%' }, { name => 'opacity', type => '0 <= float <= 100', - desc => 'The opacity of the final blend $desc' }, + desc => 'The opacity of the final blend %%desc%%' }, { name => 'offset', type => '0 <= float', desc => 'Offset relates to the starting and ending coordinates specified for the blend. This parameter is mode dependent - $desc' }, + %%desc%%' }, { name => 'repeat', type => 'enum RepeatMode', - desc => 'Repeat mode: $desc' }, + desc => 'Repeat mode: %%desc%%' }, { name => 'supersample', type => 'boolean', - desc => 'Do adaptive supersampling $desc' }, + desc => 'Do adaptive supersampling (%%desc%%)' }, { name => 'max_depth', type => '1 <= int32 <= 9', desc => 'Maximum recursion levels for supersampling', cond => 'supersample' }, @@ -133,9 +150,13 @@ HELP %invoke = ( headers => [ qw("blend.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -blend (gimage, drawable, blend_mode, paint_mode, gradient_type, opacity, - offset, repeat, supersample, max_depth, threshold, x1, y1, x2, y2); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + blend (gimage, drawable, blend_mode, paint_mode, gradient_type, opacity, + offset, repeat, supersample, max_depth, threshold, x1, y1, x2, y2); +} CODE ); } @@ -169,15 +190,15 @@ HELP; %inargs = ( &drawable_arg, { name => 'fill_mode', type => 'enum FillMode', - desc => 'The type of fill: $desc' }, + desc => 'The type of fill: %%desc%%' }, { name => paint_mode, type => 'enum PaintMode', - desc => 'The paint application mode: $desc' }, + desc => 'The paint application mode: %%desc%%' }, { name => opacity, type => '0 <= float <= 100', - desc => 'The opacity of the final bucket fill $desc' }, + desc => 'The opacity of the final bucket fill %%desc%%' }, { name => threshold, type => '0 <= float <= 255', desc => "The threshold determines how extensive the seed fill will be. It's value is specified in terms of intensity levels - \$desc. $validity" }, + %%desc%%. $validity" }, &sample_merged_arg, { name => x, type => 'float', desc => eval qq/{\$a = 'x'; "$coord";}/ }, @@ -187,9 +208,13 @@ HELP; %invoke = ( headers => [ qw ("bucket_fill.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -bucket_fill (gimage, drawable, fill_mode, paint_mode, opacity, threshold, - sample_merged, x, y); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + bucket_fill (gimage, drawable, fill_mode, paint_mode, opacity, + threshold, sample_merged, x, y); +} CODE ); } @@ -220,10 +245,8 @@ HELP &drawable_arg, { name => 'color', type => 'color', desc => 'The color to select' }, - { name => 'threshold', type => '0 <= int32 <= 255', - desc => 'Threshold in intensity levels $desc' }, - { name => 'operation', type => 'enum Operation', - desc => 'The selection operation: $desc' }, + &threshold_arg, + &operation_arg, &antialias_arg, &feather_select_args, &sample_merged_arg @@ -231,9 +254,13 @@ HELP %invoke = ( headers => [ qw("by_color_select.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' -by_color_select (gimage, drawable, color, threshold, operation, antialias, - feather, feather_radius, sample_merged); +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + by_color_select (gimage, drawable, color, threshold, operation, + antialias, feather, feather_radius, sample_merged); +} CODE ); } @@ -263,20 +290,19 @@ HELP { name => 'src_drawable', type => 'drawable', desc => 'The source drawable' }, { name => 'clone_type', type => 'enum CloneType', - desc => 'The type of clone: $desc' }, + desc => 'The type of clone: %%desc%%' }, { name => 'src_x', type => 'float', desc => 'The x coordinate in the source image' }, { name => 'src_y', type => 'float', desc => 'The y coordinate in the source image' }, &stroke_arg ); - delete $inargs[0]->{get}; %invoke = ( headers => [ qw("clone.h") ], code => <<'CODE' -clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, num_strokes, - strokes); +clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, + num_strokes, strokes); CODE ); } @@ -314,14 +340,18 @@ HELP @outargs = ( { name => 'color', type => 'color', - desc => 'The return color' } + desc => 'The return color', init => 1 } ); %invoke = ( headers => [ qw("color_picker.h") ], + vars => ['GimpImage *gimage'], code => <<'CODE' { - if (success = get_color (gimage, drawable, (int) x, (int) y, sample_merged, save_color) + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + if (success = get_color (gimage, drawable, (int) x, (int) y, + sample_merged, save_color) { color = g_new (guchar, 3); color[RED_PIX] = col_value[RED_PIX]; @@ -348,9 +378,9 @@ HELP @inargs = ( &drawable_arg, { name => 'pressure', type => '0 <= float <= 100', - desc => 'The pressure: $desc' }, + desc => 'The pressure: %%desc%%' }, { name => 'convolve_type', type 'enum Convolve (no CUSTOM)', - desc => 'Convolve type: $desc' }, + desc => 'Convolve type: %%desc%%' }, &stroke_arg ); @@ -389,8 +419,7 @@ HELP headers => [ qw("crop.h") ], code => <<'CODE' { - if (new_width > gimage->width || - new_height > gimage->height || + if (new_width > gimage->width || new_height > gimage->height || offx > (gimage->width - new_width) || offy > (gimage->height - new_height) success = FALSE; @@ -422,11 +451,10 @@ HELP { name => 'y', type => 'float', desc => 'y coordinate of upper-left corner of ellipse bounding box' }, { name => 'width', type => '0 < float', - desc => 'The width of the ellipse: $desc' }, + desc => 'The width of the ellipse: %%desc%%' }, { name => 'height', type => '0 < float', - desc => 'The height of the ellipse: $desc' }, - { name => 'operation', 'enum Selection', - desc => 'The selection operation: $desc' }, + desc => 'The height of the ellipse: %%desc%%' }, + &operation_arg, &antialias_arg, &feather_args ); @@ -434,8 +462,8 @@ HELP %invoke = ( headers => [ qw("ellipse_select.h") ], code => <<'CODE' -ellipse_select (gimage, (int) x, (int) y, (int) w, (int) h, op, antialias, - feather, feather_radius); +ellipse_select (gimage, (int) x, (int) y, (int) width, (int) height, + operation, antialias, feather, feather_radius); CODE ); } @@ -457,9 +485,9 @@ HELP &drawable_arg, &stroke_arg, { name => 'hardness', type => 'enum EraserHardness', - desc => '$desc' } + desc => '%%desc%%' } { name => 'method', type => 'enum EraserMethod', - desc => '$desc' } + desc => '%%desc%%' } ); %invoke = ( @@ -492,20 +520,18 @@ HELP @inargs = ( &drawable_arg, { name => 'flip_type', type => 'enum FlipType', - desc => 'Type of flip: $desc' } + desc => 'Type of flip: %%desc%%' } ); - @outargs = ( &drawable_arg ); - $outargs[0]->{alias} = layer; - $outargs[0]->{desc} = 'The flipped drawable'; - $outargs[0]->{no_declare} = 1; - delete $outargs[0]->{get}; + @outargs = ( &drawable_out_arg('flipped') ); %invoke = ( headers => [ qw("flip_tool.h" "tranform_core.h") ], - vars => ['TileManger *float_tiles, *new_tiles', 'Layer *layer'] + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles'], code => <<'CODE' { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + /* Start a transform undo group */ undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); @@ -541,4 +567,626 @@ CODE ); } +sub free_select { + $blurb = 'Create a polygonal selection over the specified image.'; + $help = <<'HELP'; +This tool creates a polygonal selection over the specified image. The polygonal +region can be either added to, subtracted from, or replace the contents of the +previous selection mask. The polygon is specified through an array of floating +point numbers and its length. The length of array must be 2n, where n is the +number of points. Each point is defined by 2 floating point values which +correspond to the x and y coordinates. If the final point does not connect to +the starting point, a connecting segment is automatically added. If the feather +option is enabled, the resulting selection is blurred before combining. The +blur is a gaussian blur with the specified feather radius. +HELP + + &std_pdb_misc; + + @inargs = ( + &std_image_arg, + { name => 'segs', type => 'floatarray', + desc => 'Array of points: { p1.x, p1.y, p2.x, p2.y, ..., + pn.x, pn.y}', + array => { desc => 'Number of points (count 1 coordinate as two + points)' } }, + &operation_arg, + &antialias_arg, + &feather_select_args + ); + + %invoke = ( + headers => qw("free_select.h"), + code => <<'CODE' +free_select (gimage, num_segs, segs, operation, antialias, feather, + feather_radius); +CODE + ); +} + +sub fuzzy_select { + $blurb = <<'BLURB'; +Create a fuzzy selection starting at the specified coordinates on the specified +drawable. +BLURB + + $help = <<'HELP'; +This tool creates a fuzzy selection over the specified image. A fuzzy selection +is determined by a seed fill under the constraints of the specified threshold. +Essentially, the color at the specified coordinates (in the drawable) is +measured and the selection expands outwards from that point to any adjacent +pixels which are not significantly different (as determined by the threshold +value). This process continues until no more expansion is possible. The +antialiasing parameter allows the final selection mask to contain intermediate +values based on close misses to the threshold bar at pixels along the seed fill +boundary. Feathering can be enabled optionally and is controlled with the +"feather_radius" paramter. If the sample_merged parameter is non-zero, the data +of the composite image will be used instead of that for the specified drawable. +This is equivalent to sampling for colors after merging all visible layers. In +the case of a merged sampling, the supplied drawable is ignored. If the sample +is merged, the specified coordinates are relative to the image origin; +otherwise, they are relative to the drawable's origin.' +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'x', type => 'float', + desc => 'x coordinate of initial seed fill point: (image + coordinates)' }, + { name => 'y', type => 'float', + desc => 'y coordinate of initial seed fill point: (image + coordinates)' }, + &threshold_arg, + &operation_arg, + &antialias_arg, + &feather_select_args, + &sample_merged_arg + ); + + %invoke = ( + headers => qw("fuzzy_select.h"), + vars => ['GimpImage *gimage', 'Channel *new, *old_fuzzy_mask'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + new = find_contiguous_region (gimage, drawable, antialias, threshold, + x, y, sample_merged); + old_fuzzy_mask = fuzzy_mask; + fuzzy_mask = new; + + drawable = sample_merged ? NULL : drawable; + fuzzy_select (gimage, drawbale, operation, feather, feather_radius); + + fuzzy_mask = old_fuzzy_mask; +} +CODE + ); +} + +sub paintbrush { + $blurb = 'Paint in the current brush with optional fade out parameter.'; + + $help = <<'HELP'; +This tool is the standard paintbrush. It draws linearly interpolated lines +through the specified stroke coordinates. It operates on the specified drawable +in the foreground color with the active brush. The "fade_out" parameter is +measured in pixels and allows the brush stroke to linearly fall off. The +pressure is set to the maximum at the beginning of the stroke. As the distance +of the stroke nears the fade_out value, the pressure will approach zero. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'fade_out', type => '0 < float', + desc => 'Fade out parameter: %%desc%%' }, + &stroke_arg, + { name => 'method', type => 'enum PaintMethod', + desc => '%%desc%%' } + ); + + %invoke = ( + headers => [ qw("paintbrush.h") ], + code => <<'CODE' +paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, method); +CODE + ); +} + +sub pencil { + $blurb = 'Paint in the current brush without sub-pixel sampling.'; + + $help = <<'HELP'; +This tool is the standard pencil. It draws linearly interpolated lines through +the specified stroke coordinates. It operates on the specified drawable in the +foreground color with the active brush. The brush mask is treated as though it +contains only black and white values. Any value below half is treated as black; +any above half, as white. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + &stroke_arg + ); + + %invoke = ( + headers => qw("fuzzy_select.h"), + code => 'pencil_non_gui (drawable, num_strokes, strokes);' + ); +} + +sub perspective { + $blurb = <<'BLURB'; +Perform a possibly non-affine transformation on the specified drawable. +BLURB + + $help = <<'HELP'; +This tool performs a possibly non-affine transformation on the specified +drawable by allowing the corners of the original bounding box to be arbitrarily +remapped to any values. The specified drawable is remapped if no selection +exists. However, if a selection exists, the portion of the drawable which lies +under the selection is cut from the drawable and made into a floating selection +which is then remapped as specified. The interpolation parameter can be set to +TRUE to indicate that either linear or cubic interpolation should be used to +smooth the resulting remapped drawable. The return value is the ID of the +remapped drawable. If there was no selection, this will be equal to the +drawable ID supplied as input. Otherwise, this will be the newly created and +remapped drawable. The 4 coordinates specify the new locations of each corner +of the original bounding box. By specifying these values, any affine +transformation (rotation, scaling, translation) can be affected. Additionally, +these values can be specified such that the resulting transformed drawable will +appear to have been projected via a perspective transform. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + ); + + my $pos = 0; + foreach $where (qw(upper-left upper-right lower-left lower-right)) { + foreach (qw(x y)) { + push @inargs, + { name => "$_$pos", type => 'float', + desc => "The new $_ coordinate of $where corner of original + bounding box", + alias => "trans_info[@{[ uc $_ ]}$pos]}", no_declare => 1 } + } + $pos++; + } + + @outargs = ( &drawable_out_arg('newly mapped') ); + + %invoke = ( + headers => [ qw("perspective_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'int new_layer', 'double cx, cy', 'double scalex, scaley', + 'double trans_info[8]', 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + /* Determine the perspective transform that maps from + * the unit cube to the trans_info coordinates + */ + perspective_find_transform (trans_info, m); + + cx = float_tiles->x; + cy = float_tiles->y; + scalex = 1.0; + scaley = 1.0; + if (float_tiles->width) + scalex = 1.0 / float_tiles->width; + if (float_tiles->height) + scaley = 1.0 / float_tiles->height; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + gimp_matrix_scale (matrix, scalex, scaley); + gimp_matrix_mult (m, matrix); + + /* Perspective the buffer */ + new_tiles = perspective_tool_perspective (gimage, drawable, NULL, + float_tiles, interpolation, + matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub rect_select { + $blurb = 'Create a rectangular selection over the specified image;'; + + $help = <<'HELP'; +This tool creates a rectangular selection over the specified image. The +rectangular region can be either added to, subtracted from, or replace the +contents of the previous selection mask. If the feather option is enabled, the +resulting selection is blurred before combining. The blur is a gaussian blur +with the specified feather radius. +HELP + + &std_pdb_misc; + + @inargs = ( + &std_image_arg, + { name => 'x', type => 'float', + desc => 'x coordinate of upper-left corner of rectangle' }, + { name => 'y', type => 'float', + desc => 'y coordinate of upper-left corner of rectangle' }, + { name => 'width', type => '0 < float', + desc => 'The width of the rectangle: %%desc%%' } + { name => 'height', type => '0 < float', + desc => 'The height of the rectangle: %%desc%%' } + &operation_arg, + &feather_select_args, + ); + + %invoke = ( + headers => [ qw("rect_select.h") ], + code => <<'CODE' +rect_select (gimage, (int) x, (int) y, (int) width, (int) height, + operation, feather, feather_radius); +CODE + ); +} + +sub rotate_invoker { + $blurb = <<'BLURB'; +Rotate the specified drawable about its center through the specified angle. +BLURB + + $help = <<'HELP'; +This tool rotates the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then rotated by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting rotated drawable. The return value is the ID of the rotated drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and rotated drawable. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + { name => 'angle', type => 'float', + desc => 'The angle of rotation (radians)' } + ); + + @outargs = ( &drawable_arg('rotated') ); + + %invoke = ( + headers => [ qw("rotate_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'Layer *layer', 'int new_layer', 'double cx, cy', + 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + cx = float_tiles->x + float_tiles->width / 2.0; + cy = float_tiles->y + float_tiles->height / 2.0; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + gimp_matrix_rotate (matrix, angle); + gimp_matrix_translate (matrix, +cx, +cy); + + /* Rotate the buffer */ + new_tiles = rotate_tool_rotate (gimage, drawable, NULL, angle, + float_tiles, interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* Push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub scale { + $blurb = 'Scale the specified drawable.'; + + $help = <<'HELP'; +This tool scales the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then scaled by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting scaled drawable. The return value is the ID of the scaled drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and scaled drawable. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + ); + + my $pos = 1; + foreach $where (qw(upper-left lower-right)) { + foreach (qw(x y)) { + push @inargs, + { name => "$_$pos", type => 'float', + desc => "The new $_ coordinate of $where corner of newly + scaled region", + alias => "trans_info[@{[ uc $_ ]}$pos]}", no_declare => 1 } + } + $pos++; + } + + @outargs = ( &drawable_out_arg('scaled') ); + + %invoke = ( + headers => [ qw("scale_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'int new_layer', 'double scalex, scaley', + 'double trans_info[4]', 'GimpMatrix matrix'], + code => <<'CODE' +{ + if (trans_info[X1] < trans_info[X2] && + trans_info[Y1] < trans_info[X2]) + { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + scalex = scaley = 1.0; + if (float_tiles->width) + scalex = (trans_info[X2] - trans_info[X1]) / (double) float_tiles->width +; + if (float_tiles->height) + scaley = (trans_info[Y2] - trans_info[Y1]) / (double) float_tiles->heigh +t; + + /* Assemble the transformation matrix */ + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, float_tiles->x, float_tiles->y); + gimp_matrix_scale (matrix, scalex, scaley); + gimp_matrix_translate (matrix, trans_info[X1], trans_info[Y1]); + + /* Scale the buffer */ + new_tiles = scale_tool_scale (gimage, drawable, NULL, trans_info, + float_tiles, interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* push the undo group end */ + undo_push_group_end (gimage); + } + else + success = FALSE; +} +CODE + ); +} + +sub shear { + $blurb = <<'BLURB'; +Shear the specified drawable about its center by the specified magnitude. +BLURB + + $help = <<'HELP'; +This tool shears the specified drawable if no selection exists. If a selection +exists, the portion of the drawable which lies under the selection is cut from +the drawable and made into a floating selection which is then sheard by the +specified amount. The interpolation parameter can be set to TRUE to indicate +that either linear or cubic interpolation should be used to smooth the +resulting sheared drawable. The return value is the ID of the sheard drawable. +If there was no selection, this will be equal to the drawable ID supplied as +input. Otherwise, this will be the newly created and sheard drawable. The shear +type parameter indicates whether the shear will be applied horizontally or +vertically. The magnitude can be either positive or negative and indicates the +extent (in pixels) to shear by. +HELP + + &std_pdb_misc; + + @inargs = ( + &drawable_arg, + { name => 'interpolation', type => 'boolean', + desc => 'Whether to use interpolation' } + { name => 'shear_type', type => 'enum ShearType', + desc => 'Type of shear: %%desc%%' }, + { name => 'magnitude', type => 'float', + desc => 'The magnitude of the shear' } + ); + + @outargs = ( &drawable_arg('sheared') ); + + %invoke = ( + headers => [ qw("perspective_tool.h" "tranform_core.h") ], + vars => ['GimpImage *gimage', 'TileManger *float_tiles, *new_tiles', + 'Layer *layer', 'int new_layer', 'double cx, cy', + 'GimpMatrix matrix'], + code => <<'CODE' +{ + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + + /* Start a transform undo group */ + undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); + + /* Cut/Copy from the specified drawable */ + float_tiles = transform_core_cut (gimage, drawable, &new_layer); + + cx = float_tiles->x + float_tiles->width / 2.0; + cy = float_tiles->y + float_tiles->height / 2.0; + + gimp_matrix_identity (matrix); + gimp_matrix_translate (matrix, -cx, -cy); + /* Shear matrix */ + if (shear_type == HORZ) + gimp_matrix_xshear (matrix, shear_magnitude / float_tiles->height); + else if (shear_type == VERT) + gimp_matrix_yshear (matrix, shear_magnitude / float_tiles->width); + gimp_matrix_translate (matrix, +cx, +cy); + + /* Shear the buffer */ + new_tiles = shear_tool_shear (gimage, drawable, NULL, float_tiles, + interpolation, matrix); + + /* Free the cut/copied buffer */ + tile_manager_destroy (float_tiles); + + if (new_tiles) + { + layer = transform_core_paste (gimage, drawable, new_tiles, new_layer); + success = layer != NULL; + } + else + success = FALSE; + + /* Push the undo group end */ + undo_push_group_end (gimage); +} +CODE + ); +} + +sub text { + $blurb = <<'BLURB'; +Add text at the specified location as a floating selection or a new layer. +BLURB + + $help = <<'HELP'; +This tool requires font information in the form of nine parameters: size, +foundry, family, weight, slant, set_width, spacing, registry, encoding. The +font size can either be specified in units of pixels or points, and the +appropriate metric is specified using the size_type argument. The x and y +parameters together control the placement of the new text by specifying the +upper left corner of the text bounding box. If the antialias parameter is +non-zero, the generated text will blend more smoothly with underlying layers. +This option requires more time and memory to compute than non-antialiased text; +the resulting floating selection or layer, however, will require the same +amount of memory with or without antialiasing. If the specified drawable +parameter is valid, the text will be created as a floating selection attached +to the drawable. If the drawable parameter is not valid (-1), the text will +appear as a new layer. Finally, a border can be specified around the final +rendered text. The border is measured in pixels. +HELP + + &std_pdb_misc; + $author = 'Martin Edlman'; + $date = '1998'; + + @inargs = ( + &drawable_arg, + { name => 'x', type => 'float', + desc => 'The x coordinate for the left of the text bounding box' }, + { name => 'y', type => 'float', + desc => 'The y coordinate for the top of the text bounding box' }, + { name => 'text', type => 'string', + desc => 'The text to generate', + { name => 'border', type => '-1 <= int32', + desc => 'The size of the border: %%desc%%' } + &antialias_arg, + { name => 'size', type => '0 < float', + desc => 'The size of text in either pixels or points' }, + { name => 'size_type', type => 'enum SizeType', + desc => 'The units of specified size: %%desc%%' } + ); + + foreach (qw(foundry family weight slant set-width spacing registry + encoding)) { + my $var = $_; + $var =~ s/-/_/g; + + push @inargs, { name => $var, type => 'string', + desc => qq/The font $_, "*" for any/ } + } + + @outargs = ( + { name => 'text_layer', type => 'layer', + desc => 'The new text layer' } + ); + + %invoke = ( + headers => [ qw("text_tool.h") ], + vars => ['GimpImage *gimage', 'gchar *fontname[2048]'], + code => <<'CODE' +{ + if (antialias) + size *= SUPERSAMPLE; + + success = text_get_xlfd (size, size_type, foundry, family, weight, + slant, set_width, spacing, registry, encoding, + fontname); + + if (success) + { + gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); + text_layer = text_render (gimage, drawable, x, y, fontname, text, + border, antialias); + success = text_layer != NULL; + } +} +CODE + ); +} diff --git a/tools/pdbgen/pdbgen.pl b/tools/pdbgen/pdbgen.pl index f40d81bff1..dd1035017c 100755 --- a/tools/pdbgen/pdbgen.pl +++ b/tools/pdbgen/pdbgen.pl @@ -65,7 +65,7 @@ $evalcode = <<'CODE'; $grp{$file}->{desc} = $desc if defined $desc; $grp{$file}->{code} = $code if defined $code; - foreach my $proc (@procs) { + foreach $proc (@procs) { # Reset all our PDB vars so previous defs don't interfere foreach (@procvars) { eval "undef $_" } @@ -108,6 +108,7 @@ foreach $file (@groups) { # Some important stuff require 'pdb.pl'; +require 'enums.pl'; require 'util.pl'; # Squash whitespace into just single spaces between words