#!/usr/bin/perl -w
# Generate PNG files that shows the input text with leading spaces removed.
use strict;
use File::Temp;
use constant FRAMES => 20;
use constant PAGE_OFFSET_X => 306;
use constant PAGE_OFFSET_Y => 396;
use constant CANVAS_WIDTH => 400;
use constant FONT_SCALE_FACTOR => 1.2;
use constant CROP_X => 275;
use constant CROP_Y => 650;
use constant CROP_S => 2000;
use constant RESIZE_WIDTH => 800;
# Load input
if( $#ARGV != 1 )
{
die "$0 \n";
}
my ($input_text, $output_prefix) = @ARGV;
open my $infile, "<$input_text" or die $!;
my @lines = <$infile>;
close $infile;
my $width = 0;
foreach (@lines)
{
chomp;
$width = length($_) if $width < length($_);
}
my $height = scalar @lines;
# Compute offsets
my $cx = $width / 2;
my $cy = $height / 2;
my $long_edge = $width > $height ? $width : $height;
my $spacing = CANVAS_WIDTH / $long_edge;
# Compute the amount of leading spaces that will need to be shifted
# for each row.
my @left_shift = ();
foreach my $r (@lines)
{
if( $r =~ /^(\s*)\S/ )
{
push @left_shift, length($1);
}
else
{
push @left_shift, 0;
}
}
# Generate frames
my $ps_file = tmpnam();
for(my $frame = 0; $frame < FRAMES; $frame++)
{
# Page header
my $scale = $spacing * FONT_SCALE_FACTOR;
my $ps = '%!PS' .
"\n/Courier-Bold findfont $scale scalefont setfont\n";
# Compute scaling factor for positions, using a cubic to make the
# translation accelerate at the beginning and decelerate at the end.
#
# f(x) = -2x^3 + 3x^2
# f'(x) = -6x^2 + 6x
# -> f(0) = 0
# -> f(1) = 1
# -> f'(0) = 0
# -> f'(1) = 0
my $tx = $frame / FRAMES;
my $t = -2 * ($tx * $tx * $tx) + 3 * ($tx * $tx);
# Transpose and draw each character.
#
# The four "$spacing/2" adjustments are there for consistency with
# animate_rotate_cw.pl.
for(my $y = 0; $y < $height; $y++)
{
my $dy = ($cy - $y) * $spacing - $spacing / 2;
for(my $x = 0; $x < $width; $x++)
{
# No need to render spaces
next if $x >= length($lines[$y]);
my $c = substr($lines[$y], $x, 1);
next if $c eq " ";
# Escape special characters for PostScript
if( $c =~ /[()\\]/ )
{
$c = '\\' . $c;
}
my $dx = ($x - $cx - $t * $left_shift[$y]) * $spacing + $spacing / 2;
my $px = $dx + PAGE_OFFSET_X - $spacing / 2;
my $py = $dy + PAGE_OFFSET_Y + $spacing / 2;
$ps .= "$px $py moveto ($c) show\n";
}
}
# Page footer
$ps .= "showpage\nquit\n";
# Write PostScript file
open my $outfile, ">$ps_file" or die $!;
print $outfile $ps;
close $outfile;
# Convert PostScript to PPM
my $cmd = "gs -q -dBATCH -dNOPAUSE -sDEVICE=ppmraw " .
"-r300x300 -dTextAlphaBits=4 -dGraphicsAlphaBits=4 " .
"-sOutputFile=${output_prefix}_tmp.ppm $ps_file";
system $cmd;
# Crop and resize output
$cmd = sprintf 'pamcut -left %d -top %d -width %d -height %d ' .
'%s_tmp.ppm ' .
' | pnminvert ' .
' | pamscale -xsize %d ' .
' | pnmtopng -compression 9 > %s%04d.png',
CROP_X, CROP_Y, CROP_S, CROP_S,
$output_prefix,
RESIZE_WIDTH,
$output_prefix,
$frame;
system $cmd;
}
unlink "${output_prefix}_tmp.ppm";
unlink $ps_file;