File Coverage

blib/lib/PostScript/File/Functions.pm
Criterion Covered Total %
statement 69 69 100.0
branch 12 16 75.0
condition 4 5 80.0
subroutine 11 11 100.0
pod 4 4 100.0
total 100 105 95.2


line stmt bran cond sub pod time code
1             #---------------------------------------------------------------------
2             package PostScript::File::Functions;
3             #
4             # Copyright 2012 Christopher J. Madsen
5             #
6             # Author: Christopher J. Madsen
7             # Created: 2 Feb 2012
8             #
9             # This program is free software; you can redistribute it and/or modify
10             # it under the same terms as Perl itself.
11             #
12             # This program is distributed in the hope that it will be useful,
13             # but WITHOUT ANY WARRANTY; without even the implied warranty of
14             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the
15             # GNU General Public License or the Artistic License for more details.
16             #
17             # ABSTRACT: Collection of useful PostScript functions
18             #---------------------------------------------------------------------
19              
20 2     2   2357 use 5.008;
  2         5  
  2         86  
21 2     2   85 use strict;
  2         5  
  2         85  
22 2     2   13 use warnings;
  2         2  
  2         110  
23              
24             our $VERSION = '2.21';
25             # This file is part of PostScript-File 2.21 (May 2, 2015)
26              
27 2     2   12 use Carp qw(croak);
  2         3  
  2         136  
28 2     2   11 use PostScript::File 2.20 (); # strip method
  2         42  
  2         1694  
29              
30             # Constant indexes of the arrayrefs in the _functions hash:
31             sub _id_ () { 0 } ## no critic
32             sub _code_ () { 1 } ## no critic
33             sub _requires_ () { 2 } ## no critic
34              
35             #=====================================================================
36             # Initialization:
37             #
38             # Subclasses should call __PACKAGE__->_init_module(\*DATA);
39              
40             sub _init_module
41             {
42 2     2   2 my ($class, $fh) = @_;
43              
44 2         7 my $function = $class->_functions;
45 2         4 my @keys;
46             my $routine;
47              
48 2         10 while (<$fh>) {
49 380 100       577 if (/^%-+$/) {
50 24         87 PostScript::File::->strip(all_comments => $routine);
51 24 100       57 next unless $routine;
52 22 50       69 $routine =~ m!^/(\w+)! or die "Can't find name in $routine";
53 22         46 push @keys, $1;
54 22         74 $function->{$1} = [ undef, $routine ];
55 22         32 $routine = '';
56             }
57              
58 378         715 $routine .= $_;
59             } # end while
60              
61 2         5 my $id = 'A';
62 2         10 $id .= 'A' while @keys > 26 ** length $id;
63              
64 2         10 my $re = join('|', @keys);
65 2         106 $re = qr/\b($re)\b/;
66              
67 2         5 for my $name (@keys) {
68 22         24 my $f = $function->{$name};
69 22         26 $$f[_id_] = $id++;
70              
71 22         18 my %req;
72              
73 22         169 $req{$_} = 1 for $$f[_code_] =~ m/$re/g;
74 22         27 delete $req{$name};
75              
76 22 100       56 $$f[_requires_] = [ keys %req ] if %req;
77             } # end for each $f in @keys
78              
79 2         20 close $fh;
80              
81 2         30 1;
82             } # end _init_module
83             #=====================================================================
84              
85              
86             sub new
87             {
88 2     2 1 5 my ($class) = @_;
89              
90             # Create the object:
91 2         28 bless {}, $class;
92             } # end new
93              
94             #---------------------------------------------------------------------
95             # The hash of available functions (class attribute):
96             #
97             # This is automatically per-class, so subclasses normally don't need
98             # to override it.
99              
100             {
101             my %functions;
102             sub _functions
103             {
104 11     11   17 my $self = shift;
105              
106 11   66     89 $functions{ref($self) || $self} ||= {};
      100        
107             } # end _functions
108             } # end scope of %functions
109              
110             #---------------------------------------------------------------------
111              
112              
113             sub add
114             {
115 3     3 1 7 my ($self, @names) = @_;
116              
117 3         8 my $available = $self->_functions;
118              
119 3         8 while (@names) {
120 5         8 my $name = shift @names;
121              
122 5 50       11 croak "$name is not an available function" unless $available->{$name};
123 5         11 $self->{$name} = 1;
124              
125 5 100       17 next unless my $need = $available->{$name}[_requires_];
126 2         6 push @names, grep { not $self->{$_} } @$need;
  2         10  
127             } # end while @names to add
128              
129 3         7 return $self;
130             } # end add
131             #---------------------------------------------------------------------
132              
133              
134             sub generate_procset
135             {
136 6     6 1 7 my ($self, $name) = @_;
137              
138 9         33 my @list = sort { $a->[_id_] cmp $b->[_id_] }
  6         12  
139 6         17 @{ $self->_functions }{ keys %$self };
140              
141 6         11 my $code = join('', map { $_->[_code_] } @list);
  15         39  
142              
143 6         11 my $blkid = join('', map { $_->[_id_] } @list);
  15         26  
144              
145 6 50       19 unless (defined $name) {
146 6         9 $name = ref $self;
147 6         30 $name =~ s/::/_/g;
148             }
149              
150             return wantarray
151 6 50       105 ? ("$name-$blkid", $code, $self->VERSION)
152             : $code;
153             } # end generate_procset
154             #---------------------------------------------------------------------
155              
156              
157             sub add_to_file
158             {
159 6     6 1 10 my $self = shift;
160 6         8 my $ps = shift;
161              
162 6         16 $ps->add_procset( $self->generate_procset(@_) );
163             } # end add_to_file
164              
165             #=====================================================================
166             # Package Return Value:
167              
168             __PACKAGE__->_init_module(\*DATA);
169              
170             #use YAML::Tiny; print Dump(\%function);
171              
172             =head1 NAME
173              
174             PostScript::File::Functions - Collection of useful PostScript functions
175              
176             =head1 VERSION
177              
178             This document describes version 2.21 of
179             PostScript::File::Functions, released May 2, 2015
180             as part of PostScript-File version 2.21.
181              
182             =head1 SYNOPSIS
183              
184             use PostScript::File;
185              
186             my $ps = PostScript::File->new;
187             $ps->use_functions(qw( setColor showCenter ));
188             $ps->add_to_page("1 setColor\n" .
189             "400 400 (Hello, World!) showCenter\n");
190              
191             =head1 DESCRIPTION
192              
193             PostScript::File::Functions provides a library of handy PostScript
194             functions that can be used in documents created with PostScript::File.
195             You don't normally use this module directly; PostScript::File's
196             C method loads it automatically.
197              
198             =head1 POSTSCRIPT FUNCTIONS
199              
200             =head2 boxPath
201              
202             LEFT TOP RIGHT BOTTOM boxPath
203              
204             Given the coordinates of the sides of a box, this creates a new,
205             closed path starting at the bottom right corner, across to the
206             bottom left, up to the top left, over to the top right, and then
207             back to the bottom right.
208              
209             =head2 clipBox
210              
211             LEFT TOP RIGHT BOTTOM clipBox
212              
213             This clips to the box defined by the coordinates.
214              
215             =head2 drawBox
216              
217             LEFT TOP RIGHT BOTTOM drawBox
218              
219             This calls L to and then strokes the path using the current
220             pen.
221              
222             =head2 fillBox
223              
224             LEFT TOP RIGHT BOTTOM COLOR fillBox
225              
226             This fills the path created by L with C, which can
227             be anything accepted by L.
228              
229             =head2 hLine
230              
231             WIDTH X Y hline
232              
233             Stroke a horizontal line with the current pen with the left endpoint
234             at position C, extending C points rightwards.
235              
236             =head2 setColor
237              
238             RGB-ARRAY|BW-NUMBER setColor
239              
240             This combines C and C into a single function.
241             You can provide either an array of 3 numbers for C, or
242             a single number for C. The L
243             function was designed to format the parameter to this function.
244              
245             =head2 showCenter
246              
247             X Y STRING showCenter
248              
249             This prints C centered horizontally at position X using
250             baseline Y and the current font.
251              
252             =head2 showLeft
253              
254             X Y STRING showLeft
255              
256             This prints C left justified at position X using baseline Y
257             and the current font.
258              
259             =head2 showLines
260              
261             X Y LINES SPACING FUNC showLines
262              
263             This calls C for each element of C, which should be an
264             array of strings. C is called with C on the
265             stack, and it must pop those off. C is subtracted from
266             C after every line. C will normally be C,
267             C, or C.
268              
269             =head2 showRight
270              
271             X Y STRING showRight
272              
273             This prints C right justified at position X using baseline Y
274             and the current font.
275              
276             =head2 vLine
277              
278             HEIGHT X Y vline
279              
280             Stroke a vertical line with the current pen with the bottom endpoint
281             at position C, extending C points upwards.
282              
283             =head1 METHODS
284              
285             While you don't normally deal with PostScript::File::Functions objects
286             directly, it is possible. The following methods are available:
287              
288              
289              
290             =head2 new
291              
292             $funcs = PostScript::File::Functions->new;
293              
294             The constructor takes no parameters.
295              
296              
297             =head2 add
298              
299             $funcs->add('functionRequested', ...);
300              
301             Add one or more functions to the procset to be generated. All
302             dependencies of the requsted functions are added automatically. See
303             L for the list of available functions.
304              
305              
306             =head2 add_to_file
307              
308             $funcs->add_to_file($ps, $basename);
309              
310             This is short for
311              
312             $ps->add_procset( $funcs->generate_procset($basename) );
313              
314             C<$ps> should normally be a PostScript::File object.
315             See L.
316              
317              
318             =head2 generate_procset
319              
320             ($name, $code, $version) = $funcs->generate_procset($basename);
321              
322             This collects the requsted functions into a block of PostScript code.
323              
324             C<$name> is a suitable name for the procset, created by appending the
325             ids of the requsted functions to C<$basename>. If C<$basename> is
326             omitted, it defaults to the class name with C<::> replaced by C<_>.
327              
328             C<$code> is a block of PostScript code that defines the functions. It
329             contains no comments or excess whitespace.
330              
331             C<$version> is the version number of the procset.
332              
333             In scalar context, returns C<$code>.
334              
335             =head1 DIAGNOSTICS
336              
337             =over
338              
339             =item C<< %s is not an available function >>
340              
341             You requsted a function that this version of
342             PostScript::File::Functions doesn't provide.
343              
344              
345             =back
346              
347             =head1 CONFIGURATION AND ENVIRONMENT
348              
349             PostScript::File::Functions requires no configuration files or environment variables.
350              
351             =head1 INCOMPATIBILITIES
352              
353             None reported.
354              
355             =head1 BUGS AND LIMITATIONS
356              
357             No bugs have been reported.
358              
359             =head1 AUTHOR
360              
361             Christopher J. Madsen S >>>
362              
363             Please report any bugs or feature requests
364             to S >>>
365             or through the web interface at
366             L<< http://rt.cpan.org/Public/Bug/Report.html?Queue=PostScript-File >>.
367              
368             You can follow or contribute to PostScript-File's development at
369             L<< https://github.com/madsen/postscript-file >>.
370              
371             =head1 COPYRIGHT AND LICENSE
372              
373             This software is copyright (c) 2015 by Christopher J. Madsen.
374              
375             This is free software; you can redistribute it and/or modify it under
376             the same terms as the Perl 5 programming language system itself.
377              
378             =head1 DISCLAIMER OF WARRANTY
379              
380             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
381             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
382             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
383             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
384             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
385             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
386             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
387             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
388             NECESSARY SERVICING, REPAIR, OR CORRECTION.
389              
390             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
391             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
392             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
393             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
394             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
395             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
396             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
397             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
398             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
399             SUCH DAMAGES.
400              
401             =cut
402              
403             __DATA__