#!/usr/bin/perl

use Gimp qw(:auto N_);
use Gimp::Fu;
use Gimp::Util;
use strict;

N_"/Xtns/Render"; N_"/Xtns/Render/Logos"; # i18n workaround

sub perl_fu_glowing_steel {
  my $string = shift;
  my $font = shift;
  my $size = shift;
  my $units = PIXELS;
  my $glow = shift;
  my $background = shift;
  my $radius = shift;
  my $do_highl = shift;
  my $antialias = shift;

  gimp_context_push();

  my $image = gimp_image_new(100, 100, RGB);
  gimp_image_undo_disable($image);
  my $textlayer = gimp_text_fontname($image, -1, $radius*2,
				     $radius*2, $string, 0, $antialias,
				     $size, $units, $font);
  my $width = $textlayer->width+$radius*4;
  my $height = $textlayer->height+$radius*4;
  gimp_image_resize($image, $width, $height, 0, 0);
  my $backlayer = gimp_layer_new($image, $width, $height, RGBA_IMAGE,
				 "Background", 100, NORMAL_MODE);
  gimp_image_insert_layer($image, $backlayer, 0, 1);

  gimp_layer_set_lock_alpha($textlayer,1);

  perl_fu_brushed_metal($image, $textlayer, 25, 135);

  if ($do_highl) {
    perl_fu_highlight_edges($image, $textlayer, 1);
    # Merge in the highlight so that the glow shape will include the 1-pixel
    # highlight
    my $hl_layer = (gimp_image_get_layers($image))[0];
    $textlayer = gimp_image_merge_down($image, $hl_layer, EXPAND_AS_NECESSARY);
  }
  gimp_item_set_name($textlayer, "Text");

  # Fill the background
  gimp_selection_all($image);
  gimp_context_set_foreground($background);
  gimp_edit_bucket_fill($backlayer, FG_BUCKET_FILL, NORMAL_MODE, 100, 0, 1, 0, 0);

  # Make the glow:
  perl_fu_add_glow($image, $textlayer, $glow, $radius);

  gimp_image_undo_enable($image);
  gimp_selection_none($image);
  gimp_image_set_active_layer($image,$backlayer);

  gimp_context_pop();
  gimp_display_new($image);

  return $image;
}

sub perl_fu_add_glow {
  my $image = shift;
  my $drawable = shift;
  my $color = shift;
  my $radius = shift;
  my $old_draw = $drawable;
  my $is_float = 0;
  my $old_sel = gimp_selection_save($image);

  gimp_image_undo_group_start($image);

  if (!gimp_item_is_layer($drawable)) {
    die("add_glow: Only layers can have glow added");
  }

  if (!gimp_drawable_has_alpha($drawable)) {
    my($sel,$x1,$y1,$x2,$y2) = gimp_selection_bounds($image);
    if ($sel) {
      $is_float = 1;
      $drawable = gimp_selection_float($drawable,0,0);
    } else {
      die("add_glow: Need a selection to work on");
    }
  }

  my $type = gimp_drawable_type($drawable);
  my $glow = gimp_layer_new($image, gimp_image_width($image),
			    gimp_image_height($image), $type, "Glow layer",
			    100, NORMAL_MODE);
  my $lnum = $image->get_item_position($drawable);
  gimp_image_insert_layer($image, $glow, 0, $lnum);

  # Clear out the new layer
  gimp_selection_all($image);
  gimp_edit_clear($glow);
  # Add the glow

  gimp_context_push();

  gimp_context_set_foreground($color);
  gimp_image_select_item($image, CHANNEL_OP_REPLACE, $drawable);
  gimp_selection_grow($image, $radius);
  gimp_selection_feather($image, $radius*1.5);
  gimp_edit_bucket_fill($glow,FG_BUCKET_FILL,NORMAL_MODE,100,255,0,0,0);
  gimp_image_select_item($image, CHANNEL_OP_REPLACE, $drawable);
  gimp_edit_clear($glow);

  $image->select_item(CHANNEL_OP_REPLACE, $old_sel);
  gimp_floating_sel_anchor($drawable) if $is_float;
  gimp_image_set_active_layer($image,$old_draw);
  gimp_image_undo_group_end($image);

  gimp_context_pop();
  gimp_displays_flush();
}

sub perl_fu_brushed_metal {
  my $image = shift;
  my $drawable = shift;
  my $length = shift;
  my $angle = shift;
  my $use_gradient = shift;
  my $gradient = shift;

  gimp_image_undo_group_start($image);

  # A whole lot of layer fiddling to get around the fact that
  # plug_in_mblur does the wrong thing with borders....
  my($bset, $x1, $y1, $x2, $y2) = gimp_selection_bounds($image);
  if (!$bset) {
    if(gimp_drawable_has_alpha($drawable)) {
      gimp_image_select_item($image, CHANNEL_OP_REPLACE, $drawable);
    } else {
      gimp_selection_all($image);
    }
    my $ignore;
    ($ignore, $x1, $y1, $x2, $y2) = gimp_selection_bounds($image);
  }
  $x1-=$length;
  $y1-=$length;
  $x2+=$length;
  $y2+=$length;
  my $width = abs($x2-$x1);
  my $height = abs($y2-$y1);
  my $templ = gimp_layer_new($image, $width, $height, RGBA_IMAGE, "Temp",
			     100, NORMAL_MODE);
  gimp_image_insert_layer($image, $templ, 0, 0);
  gimp_layer_set_offsets($templ, $x1+$length, $y1+$length);
  my $target_select = gimp_selection_save($image);
  gimp_selection_none($image);

  # Render the actual effect into our temporary layer
  plug_in_solid_noise($image, $templ, 0, 0, time(), 1, 1.5, 2.5);

  perl_fu_map_to_gradient($image, $templ, $gradient)
    if $use_gradient && defined($gradient) && $gradient ne '';

  gimp_brightness_contrast($templ, 50, 0);
  plug_in_noisify($image, $templ, 0, 0.3, 0.3, 0.3, 0);
  plug_in_mblur($image, $templ, 0, $length, $angle, 0.0, 0.0);

  # Now put it into the target layer
  $image->select_item(CHANNEL_OP_REPLACE, $target_select);
  gimp_edit_copy($templ);
  my $float = gimp_edit_paste($drawable, 0);
  gimp_layer_set_offsets($float, $x1+$length, $y1+$length);
  gimp_floating_sel_anchor($float);
  gimp_image_remove_layer($image,$templ);
  # gimp_item_delete($templ);

  gimp_image_undo_group_end($image);

  gimp_displays_flush();
}

sub perl_fu_highlight_edges {
  my $image = shift;
  my $drawable = shift;
  my $pixels = shift;
  my $old_draw = $drawable;
  my $is_float = 0;
  my $old_sel = gimp_selection_save($image);

  gimp_image_undo_group_start($image);

  if (!gimp_item_is_layer($drawable)) {
    gimp_message("highlight_edges: Only layers can be highlighted!");
    return;
  }

  if (!gimp_item_get_visible($drawable)) {
    gimp_message("highlight_edges: The active layer must be visible!");
    return;
  }

  if (!gimp_drawable_has_alpha($drawable)) {
    my($sel,$x1,$y1,$x2,$y2) = gimp_selection_bounds($image);
    if ($sel) {
      $is_float = 1;
      $drawable = gimp_selection_float($drawable,0,0);
    } else {
      die("highlight_edges: Need a selection (or alpha layer) to work on");
    }
  }

  gimp_image_select_item($image, CHANNEL_OP_REPLACE, $drawable);
  my $white = gimp_layer_copy($drawable,0);
  my $black = gimp_layer_copy($drawable,0);
  my $lnum = $image->get_item_position($drawable);
  gimp_image_insert_layer($image, $black, 0, $lnum);
  gimp_image_insert_layer($image, $white, 0, $lnum);

  gimp_context_push();

  gimp_context_set_foreground([255,255,255]);
  gimp_edit_bucket_fill($white,FG_BUCKET_FILL,NORMAL_MODE,100,255,0,0,0);
  gimp_context_set_foreground([0,0,0]);
  gimp_edit_bucket_fill($black,FG_BUCKET_FILL,NORMAL_MODE,100,255,0,0,0);
  gimp_layer_translate($white, -1*$pixels, -1*$pixels);
  gimp_layer_translate($black, 1*$pixels, 1*$pixels);
  $white = gimp_image_merge_down($image, $white, EXPAND_AS_NECESSARY);
  gimp_item_set_name($white, "Edge Highlight");
  gimp_image_select_item($image, CHANNEL_OP_REPLACE, $drawable);
  gimp_edit_clear($white);

  $image->select_item(CHANNEL_OP_REPLACE, $old_sel);
  gimp_floating_sel_anchor($drawable) if $is_float;
  # gimp_image_set_active_layer($image,$old_draw);
  gimp_image_undo_group_end($image);

  gimp_context_pop();
  gimp_displays_flush();
}

# Register the plug-ins:

register
  "highlight_edges",
  "Frame an alpha layer with black and white edges",
  "Highlight the edges of an alpha layer and make ".
	"it appear to have height. Not quite the same as a beveled edge, ".
	"this is a somewhat more subtle technique.",
  '', '', '',
  N_"<Image>/Filters/Render/Highlight Edges...",
  "*",
  [
   [PF_INT32, "edging", "Pixels (non-functional)", 1]
  ],
  \&perl_fu_highlight_edges;

register
  "brushed_metal",
  "Create a brushed metal surface effect",
  "Make a surface (selected area) look like ".
	"brushed metal (kind of like steel).",
  '', '', '',
  N_"<Image>/Filters/Render/Pattern/Brushed Metal...",
  "*",
  [
   [PF_SLIDER,   "stroke_length", "Length", 25, [1, 100, 1]],
   [PF_SLIDER,   "angle", "Angle (0-359)", 135, [0, 359, 1]],
   [PF_BOOL,     "use_gradient", "use the gradient specified below?", 0],
   [PF_GRADIENT, "gradient", "Default"],
  ],
  \&perl_fu_brushed_metal;

register
  "add_glow",
  "Add a glow behind an alpha layer",
  "Add a glowing layer behind an existing layer. This ".
	"is very different from drop shadows, as the glow will extend out ".
	"in the given radius from all edges of the layer.",
  '', '', '',
  N_"<Image>/Filters/Render/Add Glow",
  "*",
  [
   [PF_COLOR, "glow_color", "Color", [0,0,1.0]],
   [PF_SPINNER, "glow_radius", "Radius", 10, [1, 1000, 1]]
  ],
  \&perl_fu_add_glow;

register
  "glowing_steel",
  "Render metal surface over glowing background",
  "Create the effect of a metallic surface over ".
	"a glowing surface. This effect was inspired by a poster for the ".
	"film \"Lost In Space\".",
  '', '', '',
  N_"<Image>/File/Create/Logos/Glowing Steel",
  undef,
  [
   [PF_STRING, "string", "Logo text", "GET LOST"],
   # The font in the poster was like "cobalt extended"
   [PF_FONT, "font", "Logo font", "Bitstream Charter Bold"],
   [PF_SPINNER, "size", "Font size (pixels)", 100, [0, 3000, 1]],
   [PF_COLOR, "glow_color", "Glow color", [1.0, 0.8157, 0]],
   [PF_COLOR, "background", "Background color", [0x00, 0x00, 0x00]],
   [PF_INT32, "glow_radius", "Glow radius", 4],
   [PF_TOGGLE, "highlight_edges", "Highlight edges", 0],
   [PF_TOGGLE, "antialias", "Anti-alias text", 1]
  ],
  \&perl_fu_glowing_steel;

exit main;
__END__

=head1 NAME

glowing_steel - Logo plugin for GIMP

=head1 SYNOPSIS

  <Image>/File/Create/Logos/Glowing Steel
  <Image>/Filters/Render/Brushed Metal
  <Image>/Filters/Render/Highlight Edges
  <Image>/Filters/Render/Add Glow

=head1 DESCRIPTION

Produce logos and other such nifty things which appear to be made of
steel and floating over a glowing cloud.  This plug-in also includes
several filters for performing the various stages of this logo
(i.e. brushed steel, add glow, highlight edges).

This plugin renders the given text in the given font and size in a logo
style that combines the I<Brushed Metal> effect with the I<Highlight Edges>
and I<Add Glow> effects. The text is surfaced with brushed metal, and
highlighted, and the glow is added in the background.

This plug-in also includes the effects listed above as separate tools
which may be used independent of creating a logo. These tools are:

=over 5

=item Brushed Metal

Takes length of brush strokes and angle, and renders a brushed metal surface
into the target drawable.

PDB call:

  perl_fu_brushed_metal(image, drawable, length, angle)

C<length> must be greater than 1.

=item Highlight Edges

Takes a number of pixels and adds a black/white highlight to the drawable.
Target drawable must be an alpha layer.

PDB call:

  perl_fu_highlight_edges(image, drawable, pixels)

=item Add Glow

Takes a color and radius, and renders a fuzzy glow in the given color,
out to the given radius behind the target drawable. This is added as
a new layer, and the target drawable must be an alpha layer.

PDB call:

  perl_fu_add_glow(image, drawable, color, radius)

=back

=head1 PARAMETERS

The following parameters can be set by the user (or caller) of glowing_steel:

=over 5

=item B<String>

The string to display

=item B<Font>

The Font to render the string in.

=item B<Size>

The size to use for the font.

=item B<Glow Color>

The color to use for the background glow.

=item B<Background Color>

The color to use for the background layer.

=item B<Glow Radius>

The radius in pixels that the glow should emanate from the edge of the text.

=item B<Highlight Edges>

This toggle tells glowing_steel if it should (true) or should not
(false) add one-pixel black/white edge highlighting. Default is to
add the highlighting.

=item B<Antialias>

This toggle will turn on (true) or off (false) font antialiasing. This
should only be used if you find that this plugin crashes because the font
you chose could not be antialiased (the gimp will display an error suggesting
that you turn off antialiasing).

=back

PDB call:

  my $image = perl_fu_glowing_metal( string, font, size, glow_color,
	back_color, glow_radius, highlight, antialias)

=head1 AUTHOR

Aaron Sherman <ajs@ajs.com>

=head1 DATE

Version 1.0a released 1999-06-14

=head1 LICENSE

Written in 1999 (c) by Aaron Sherman <ajs@ajs.com>.

This plugin may be distributed under the same terms as Gimp itself.
