Acme-Pony
view release on metacpan or search on metacpan
lib/Acme/Pony.pm view on Meta::CPAN
package Acme::Pony;
$VERSION = '1.1.2';
open 0 or print "Can't Pony '$0'\n" and exit;
(my $code = join "", <0>) =~ s/.*^\s*use\s+Acme::Pony\s*;\n//sm;
if($code!~/^[buffyX\s]*$/i) { # if it hasn't been encoded
my $code=ponyize("$code\n__END__");
open(0, ">$0") or print "Can't Ponyize $0\n" and exit();
print {0} "use Acme::Pony;\n$code" and exit();
} else {
$code=unpony($code); # $code=~s/\n__END__//;
eval($code);
exit();
}
sub ponyize {
my @chars = split(//, unpack "b*", pop);
my $i=0;
my @BUFFY=qw(B U F F Y);
my @buffy=qw(b u f f y);
foreach (@chars) {
$_ = $_ ? $BUFFY[$i] : $buffy[$i];
$i++; $i %= 5;
}
@chars=scalepony(@chars);
join('',@chars);
}
sub unpony {
my @chars=grep { /[buffy]/i; } split(//, pop);
foreach (@chars) {
$_=($_=~/[buffy]/)?0:1;
}
pack "b*", join '', @chars;
}
sub scalepony {
my @chars = @_;
my $chars = join '', @chars;
my $wantlength = length $chars;
my $scale;
# What scale do we want?
if ($wantlength > 201242) {
$scale = 1000 * sqrt($wantlength / 201242);
} else {
$scale = 1000 / sqrt(201242 / $wantlength);
}
$scale *= 0.95;
# These were worked out by hand with very accurate graph paper
my @xpoints = (0.26735840061026, 0.290728815714195, 0.297102536393109, 0.299227321848579, 0.322598690483758, 0.348092937511919, 0.36933761362914, 0.403331002479181, 0.430951624181552, 0.450073104062043, 0.471317780179264, 0.484066492912084, 0.49681...
# ... or I may have used Sketch...
my @ypoints = (0.0303060573188429, 0.0417852818858603, 0.0264797254557372, 0.0150004436442946, 0.0417852818858603, 0.0666571259291486, 0.0685702346162763, 0.0915289699724368, 0.118313922702853, 0.141272371836888, 0.169970719476557, 0.21014800546111...
# Scale the points (with ASCII 'fixed' font size scaling too)
@xpoints = map { $_ *= $scale; $_ = int($_) } @xpoints;
@ypoints = map { $_ *= $scale * 5 / 9; $_ = int($_) } @ypoints;
my $n = @xpoints;
return if ($n < 3); # not even a triangle, boring
# Find the min and max y values
my($miny, $maxy) = ($ypoints[0], $ypoints[0]);
foreach my $y (@ypoints) {
if ($y < $miny) {
$miny = $y;
} elsif ($y > $maxy) {
$maxy = $y}
}
my @ascii;
# Can you say "generic polygon scanline fill"?
foreach my $y ($miny .. $maxy) {
my($ind1, $ind2, $y1, $y2, $x1, $x2, @polyints);
foreach my $i (0 .. $n-1) {
if (!$i) {
$ind1 = $n-1;
$ind2 = 0;
} else {
$ind1 = $i-1;
$ind2 = $i;
}
$y1 = $ypoints[$ind1];
$y2 = $ypoints[$ind2];
if ($y1 < $y2) {
$x1 = $xpoints[$ind1];
$x2 = $xpoints[$ind2];
} elsif ($y1 > $y2) {
$y2 = $ypoints[$ind1];
$y1 = $ypoints[$ind2];
$x2 = $xpoints[$ind1];
$x1 = $xpoints[$ind2];
} else {
next;
}
if (($y >= $y1) && ($y < $y2)) {
push @polyints, ($y-$y1) * ($x2-$x1) / ($y2-$y1) + $x1;
} elsif (($y == $maxy) && ($y > $y1) && ($y <= $y2)) {
push @polyints, ($y-$y1) * ($x2-$x1) / ($y2-$y1) + $x1;
}
}
@polyints = sort { $a <=> $b } @polyints;
while (@polyints) {
my($x1, $x2) = (pop @polyints, pop @polyints);
($x1, $x2) = ($x2, $x1) if $x1 > $x2;
foreach my $x ($x1 .. $x2) {
$ascii[$y][$x1++] = 'X';
}
( run in 1.232 second using v1.01-cache-2.11-cpan-5735350b133 )