File Coverage

blib/lib/PostScript/EPSF.pm
Criterion Covered Total %
statement 89 110 80.9
branch 37 56 66.0
condition 20 42 47.6
subroutine 8 8 100.0
pod 0 3 0.0
total 154 219 70.3


line stmt bran cond sub pod time code
1             package PostScript::EPSF;
2              
3 1     1   739 use strict;
  1         2  
  1         44  
4 1     1   7 use vars qw($VERSION @EXPORT @EXPORT_OK);
  1         1  
  1         144  
5              
6             $VERSION = "0.01";
7              
8             require Exporter;
9             *import = \*Exporter::import;
10              
11             @EXPORT=qw(include_epsf);
12             @EXPORT_OK=qw(epsf_prolog);
13              
14              
15             sub epsf_prolog
16             {
17 1     1   6 use vars qw($EPSF_PROLOG_DONE);
  1         6  
  1         1519  
18 2 100   2 0 15 print <<"EOT" unless $EPSF_PROLOG_DONE++;
19              
20             /BeginEPSF {
21             /b4_Inc_state save def
22             /dict_count countdictstack def
23             /op_count count 1 sub def
24             userdict begin
25             /showpage {} def
26             0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin
27             10 setmiterlimit [] 0 setdash newpath
28             /languagelevel where
29             {
30             1 ne {
31             false setstrokeadjust
32             false setoverprint
33             } if
34             } if
35             } bind def
36              
37             /EndEPSF {
38             count op_count sub {pop} repeat
39             countdictstack dict_count sub {end} repeat
40             b4_Inc_state restore
41             } bind def
42              
43             EOT
44             }
45              
46              
47             sub include_epsf
48             {
49 2     2 0 249 my %para;
50 2         12 while (my($k,$v) = splice(@_, 0, 2)) {
51 13         41 $k =~ s/^-//;
52 13         51 $para{$k} = $v;
53             }
54              
55             #use Data::Dumper; print STDERR Dumper(\%para);
56              
57 2   50     9 my $file = delete $para{"file"} ||
58             die "Mandatory -file argument is missing";
59            
60              
61 2         7 local(*EPS);
62 2 50       93 open(EPS, $file) || die "Can't open $file: $!";
63 2         5 my($llx, $lly, $urx, $ury);
64 0         0 my @eps;
65 2         74 while () {
66 516 100 100     2748 if (/^%%BoundingBox:\s*(.*)/) {
    100          
67 2         25 ($llx, $lly, $urx, $ury) = split(' ', $1);
68             } elsif (/^\s*%/ || /^\s*$/) {
69             # always skip other comments and empty lines
70             } else {
71 370         989 push(@eps, $_);
72             }
73             }
74 2         34 close(EPS);
75 2 50       9 die "Missing Bounding box in $file" unless defined $ury;
76              
77              
78              
79 2         8 my $xscale = delete $para{"xscale"};
80 2         7 my $yscale = delete $para{"yscale"};
81              
82             # Calculate width/height of included file
83 2         14 my $w = $urx - $llx;
84 2         3 my $h = $ury - $lly;
85              
86 2 100       13 if (my $width = delete $para{"width"}) {
87 1         6 $xscale = $width / $w;
88             }
89              
90 2 50       10 if (my $height = delete $para{"height"}) {
91 0         0 $yscale = $height / $h;
92             }
93            
94 2 100       13 if (my $scale = delete $para{"scale"}) {
95 1         4 for ($xscale, $yscale) {
96 2 50       12 $_ = $scale unless $_;
97             }
98             }
99              
100 2 50 66     14 $xscale = $yscale if $yscale && !$xscale;
101 2 100 66     12 $yscale = $xscale if $xscale && !$yscale;
102              
103 2 50       6 if ($xscale) {
104 2         5 $w = $w * $xscale;
105 2         4 $h = $h * $yscale;
106             }
107              
108 2 50       11 if (my $pos = delete $para{"pos"}) {
109 2         9 $pos =~ s/^\s*//;
110 2         22 @para{"x", "y"} = split(/\s*[,\s]\s*/, $pos);
111             }
112 2   50     8 my $x = delete $para{"x"} || 0;
113 2   50     7 my $y = delete $para{"y"} || 0;
114              
115 2   50     9 my $anchor = delete $para{"anchor"} || "c";
116 2 100       12 if ($anchor =~ /w/) {
    50          
117             # no need to adjust $x
118             } elsif ($anchor =~ /e/) {
119 1         3 $x -= $w;
120             } else {
121 0         0 $x -= $w/2;
122             }
123 2 50       11 if ($anchor =~ /s/) {
    100          
124             # no need to adjust $y
125             } elsif ($anchor =~ /n/) {
126 1         3 $y -= $h;
127             } else {
128 1         5 $y -= $h/2;
129             }
130              
131 2         5 my $rotate = delete $para{"rotate"};
132              
133 2         5 my $clip = delete $para{"clip"};
134 2         5 my $background = delete $para{"background"};
135 2   50     11 my $boarder = delete $para{"boarder"} || 0;
136              
137 2 50 33     25 if ($^W && %para) {
138 0         0 for (sort keys %para) {
139 0         0 warn "Unrecognized parameter: -$_ => $para{$_}\n";
140             }
141             }
142              
143 2         11 epsf_prolog();
144              
145 2         6 print "\nBeginEPSF\n";
146 2 50 66     22 if ($rotate || $xscale || $clip || $background) {
      33        
      33        
147 2         24 print "$x $y translate\n";
148 2 100       17 print "$rotate rotate\n" if $rotate;
149 2 50 33     7 if ($clip || $background) {
150 2         4 my $llx = 0;
151 2         4 my $lly = 0;
152 2         3 my $urx = $w;
153 2         23 my $ury = $h;
154 2 50       6 if ($boarder) {
155 0         0 $llx -= $boarder;
156 0         0 $lly -= $boarder;
157 0         0 $urx += $boarder;
158 0         0 $ury += $boarder;
159             }
160 2         8 print "$llx $lly moveto $urx $lly lineto\n";
161 2         11 print "$urx $ury lineto $llx $ury lineto closepath\n";
162 2 50       5 print "clip\n" if $clip;
163 2 100       7 if ($background) {
164 1         3 print "gsave ", color_to_ps($background), " fill grestore\n";
165             }
166 2         4 print "newpath\n";
167             }
168 2 50       19 print "$xscale $yscale scale\n" if $xscale;
169 2         15 print 0-$llx, " ", 0-$lly, " translate\n";
170             } else {
171 0         0 print $x-$llx, " ", $y-$lly, " translate\n";
172             }
173              
174 2         5 print "%%BeginDocument: $file\n";
175 2         215 print @eps;
176 2         5 print "%%EndDocument: $file\n";
177 2         47 print "EndEPSF\n\n";
178              
179             }
180              
181             BEGIN
182             {
183 1     1   7 use vars qw(%color_names);
  1         3  
  1         168  
184 1     1   361 %color_names = (
185             black => 0,
186             white => 1,
187              
188             red => "#f00",
189             green => "#0f0",
190             blue => "#00f",
191             yellow => "#ff0",
192             magenta => "#f0f",
193             cyan => "#0ff",
194             );
195             }
196              
197              
198             # should probably go into it's own module
199             sub color_to_ps
200             {
201 1   50 1 0 5 my $color = lc(shift || "");
202 1         3 $color =~ s/^\s+//;
203 1         3 $color =~ s/\s+$//;
204              
205 1   33     5 $color = $color_names{$color} || $color;
206              
207 1 50       9 if ($color =~ /^\d+(?:\.\d+)?$/) {
208 1 50       3 $color = 1 if $color > 1;
209 1         16 return sprintf "%.3f setgray", $color;
210             }
211              
212 0 0 0       if ($color =~ /^\#([0-9a-f]+)$/ && (length($1) % 3) == 0) {
213 0           my $len = int(length($1) / 3);
214 0           my $fff = 2 ** ($len*4) - 1;
215 0           $color = $1;
216 0           my @rgb;
217 0           while (length $color) {
218 0           push(@rgb, hex(substr($color, 0, $len)) / $fff);
219 0           substr($color, 0, $len) = '';
220             }
221 0           return join(" ", map {sprintf "%.3f", $_} @rgb), " setrgbcolor";
  0            
222             }
223              
224 0           return; # did not understand
225             }
226              
227             1;