File Coverage

blib/lib/Text/JavE.pm
Criterion Covered Total %
statement 3 129 2.3
branch 0 52 0.0
condition n/a
subroutine 1 8 12.5
pod 5 7 71.4
total 9 196 4.5


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2            
3             package Text::JavE;
4 1     1   24852 use strict;
  1         2  
  1         1830  
5            
6             our $VERSION='0.0.3';
7            
8             =head1 NAME
9            
10             Text::JavE - view and manipulate ascii art and manipulation files created in JavE.
11            
12             =head1 DESCRIPTION
13            
14             JavE (http://www.jave.de/) is an excellent Ascii art editor and animator
15             written in Java. Unfortunately it doesn't yet have a scripting interface.
16             This module aims to make the work of processing its standard files (.jmov)
17             easy within Perl.
18            
19             =head1 SYNOPSIS
20            
21             use Text::JavE;
22            
23             my $j = new Text::JavE;
24             while (my $file=shift @ARGV) {
25             $j->open_jmov($file);
26             for (@{$j->{frames}}) {
27             system "cls"; # on Win32. Try system "clear" on Unix.
28             $_->display;
29             my $time = $_->{msec};
30             select (undef, undef, undef, $time/1000);
31             }
32             }
33            
34             =head2 new()
35            
36             Constructor. Returns a Text::JavE object which can play or otherwise
37             manipulate jmov files.
38            
39             =cut
40            
41             sub new {
42 0     0 1   my $class=shift;
43 0           my $self={
44             decoded => [],
45             };
46 0           return bless {}, $class;
47             }
48            
49             =head2 decode($text)
50            
51             Internal method to decode a jmov line containing a compressed ascii frame.
52             There are 2 submethods decode_a and decode_b implementing the various
53             encoding algorithms JavE currently uses.
54            
55             =cut
56            
57             sub decode {
58 0     0 1   my $self=shift;
59 0           my $text=shift;
60 0           $self->{code}=$text;
61 0 0         $text=~s/^([A-Z])(\d+) (\d+) // or die "Text::JavE: invalid format: $text\n";
62 0           (my $alg, $self->{xsize}, $self->{ysize})=($1, $2, $3);
63 0           $self->{algorithm} = $alg;
64            
65 0 0         if ($alg eq "A") { $self->decode_a($text); }
  0 0          
66 0           elsif ($alg eq "B") { $self->decode_b($text); }
67             else {
68 0           warn "Unsupported algorithm: $alg\n" ;
69 0           return;
70             }
71             }
72            
73             sub decode_a {
74 0     0 0   my $self=shift;
75 0           my $text=shift;
76 0           my @decoded; my $decode_line='';
  0            
77 0           $self->{decoded}=\@decoded;
78 0           my ($x, $y) = ($self->{xsize}, $self->{ysize});
79 0           while ($text) {
80             # print "($text)\n\n";
81            
82             # Add normal text
83 0 0         if ($text=~s/^([^\%]+)//) {
84 0           $decode_line.=$1;
85             # print "($1)\n";
86             }
87            
88             # Add % signs signalled by %%
89 0 0         if ($text=~s/^((?:%%)+)//) {
90 0           $decode_line.='%' x (length($1)/2);
91             }
92            
93             # Add newlines (%0)
94 0 0         if ($text=~s/^%0//) {
95 0 0         if (length $decode_line > $x) {
96 0           warn "Line longer than $x declared!\n";
97             }
98 0           push @decoded, $decode_line;
99 0           $decode_line='';
100             }
101            
102             # Add repeated number characters (%3%8 e.g. 3 x "8")
103 0 0         if ($text=~s/^%([1-9]\d*)%(\d)//) {
104 0           $decode_line.=( $2 x $1);
105             #print "($2 x $1)\n";
106             }
107            
108             # Add repeated characters (%9x %3%% etc.)
109 0 0         if ($text=~s/^%([1-9]\d*)([^%0-9]|%%)//) {
110 0           $decode_line.=( $2 x $1);
111             #print "($2 x $1)\n";
112             }
113            
114             }
115 0 0         if (length $decode_line > $x) {
116 0           warn "Line longer than $x declared!\n";
117             }
118 0 0         if (@decoded > $y) {
119 0           warn "More than $y lines declared!\n";
120             }
121 0           push @decoded, $decode_line;
122             }
123            
124             sub decode_b {
125 0     0 0   my $self=shift;
126 0           my $text=shift;
127 0           my ($x, $y) = ($self->{xsize}, $self->{ysize});
128             #print "($x, $y)\n";
129 0           my @decoded=unpack( ("A$x" x $y), $text);
130 0           $self->{decoded}=\@decoded;
131             }
132            
133             =head2 display()
134            
135             Shows the current frame.
136            
137             =cut
138            
139             sub display {
140 0     0 1   my $self=shift;
141 0           my @decoded=@{$self->{decoded}};
  0            
142 0           my $y=$self->{ysize};
143 0           push @decoded, ('') x ($y-@decoded);
144 0           print join "\n", @decoded;
145 0           print "\n";
146             }
147            
148             =head2 open_clipart($file)
149            
150             Opens a clipart file in JavE's .jcf format.
151             (As far as I know this isn't officially documented, but a
152             number of sample files are distributed with JavE).
153            
154             =cut
155            
156             sub open_clipart {
157 0     0 1   my $self=shift;
158 0           my $file=shift;
159 0           my @clips;
160 0           $self->{clips}=\@clips;
161            
162 0 0         open (JCF, '<', $file) or die "Couldn't open file $file: $!\n";;
163 0           while (my $title=) {
164 0           my $j=Text::JavE->new;
165 0           chomp $title;
166 0           chomp(my $artist=);
167 0           chomp(my $clip=);
168 0           ; # discard empty line;
169 0 0         if ($j->decode($clip)) {
170 0           push @clips, {
171             title => $title,
172             artist => $artist,
173             clip => $j,
174             };
175             }
176             }
177             }
178            
179            
180             =head2 open_jmov($file)
181            
182             Opens a file in jmov format.
183             This format is described in detail at
184             http://www.jave.de/player/jmov_specification.html
185            
186             A sample Chickenman animation is included in the
187             distribution as t.jmov. More can be found at
188             http://osfameron.perlmonk.org/chickenman/
189             Other jmov files can be found at http://www.jave.de
190            
191             =cut
192            
193             sub open_jmov {
194 0     0 1   my $self=shift;
195 0           my $file=shift;
196 0           my (@frames, %frames);
197 0           $self->{frames}=\@frames;
198 0           $self->{frames_dict}=\%frames;
199 0           my $framenum=0;
200            
201 0 0         open (JMOV, '<', $file) or die "Couldn't open file $file: $!\n";;
202 0           my $lnum=0;
203 0           my $frame;
204 0           $self->{curr_frame}=\$frame;
205 0           while (my $line=) {
206 0           print "$lnum.";
207             #print "[$lnum]\t$line\n";
208 0           $lnum++;
209 0 0         $line=~/^(.):(.*)$/ or die "JMOV: invalid format at line $lnum: $line\n";
210 0           my ($action, $data)=($1, $2);
211 0           CASE: for ($action) {
212 0 0         /!/ and do { $self->{filename}=$data; last CASE};
  0            
  0            
213 0 0         /\*/ and do { $self->{title} =$data; last CASE};
  0            
  0            
214 0 0         /D/ and do { $self->{date} =$data; last CASE};
  0            
  0            
215 0 0         /J/ and do {
216 0           $frame=new Text::JavE;
217 0           $framenum++;
218 0           for (qw(cursorpos cpos2 colour msec action)) {
219 0           $frame->{$_} = $self->{$_};
220             }
221 0           $frame->{num}=$framenum;
222 0           $frame->{frametitle}="frame $framenum";
223 0           $frame->decode($data);
224 0           push @frames, $frame;
225 0           last CASE};
226 0 0         /\|/ and do { $self->{cursorpos}=$data; $frame->{cursorpos}=$data; last CASE};
  0            
  0            
  0            
227 0 0         /\^/ and do { $self->{cpos2}=$data; $frame->{cpos2}=$data; last CASE};
  0            
  0            
  0            
228 0 0         /\+/ and do { $self->{msec}=$data; $frame->{msec}=$data; last CASE};
  0            
  0            
  0            
229 0 0         /C/ and do { $self->{colour}=$data; $frame->{colour}=$data; last CASE};
  0            
  0            
  0            
230 0 0         /A/ and do { $self->{action}=$data; $frame->{action}=$data; last CASE};
  0            
  0            
  0            
231 0 0         /T/ and do { $frame->{frametitle}=$data;
  0            
232             # print $data;
233 0           last CASE};
234             }
235             }
236 0           for (@frames) {
237 0           push @{$frames{$_->{frametitle}}}, $_;
  0            
238             };
239 0 0         close JMOV or die;
240             # print "DONE!";
241             }
242            
243             =head1 BUGS
244            
245             Code is boneheaded and documentation is poor in v0.0.2.
246             (In v.0.0.1 it consisted of "blah blah blah" so at least
247             it's improving).
248            
249             =head1 AUTHOR
250            
251             osfameron - osfameron@cpan.org
252            
253             =cut
254            
255             1; # return true value