#!/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;