File Coverage

blib/lib/Text/Amuse/Output/Image.pm
Criterion Covered Total %
statement 100 103 97.0
branch 45 48 93.7
condition 20 25 80.0
subroutine 15 15 100.0
pod 12 12 100.0
total 192 203 94.5


line stmt bran cond sub pod time code
1             package Text::Amuse::Output::Image;
2 44     44   66577 use strict;
  44         1443  
  44         1087  
3 44     44   456 use warnings;
  44         80  
  44         864  
4 44     44   187 use utf8;
  44         70  
  44         216  
5              
6             =head1 NAME
7              
8             Text::Amuse::Output::Image -- class to manage images
9              
10             =head1 SYNOPSIS
11              
12             The module is used internally by L, so everything here is
13             pretty much internal only (and underdocumented).
14              
15             =head1 CONSTRUCTORS
16              
17             =over 4
18              
19             =item new(filename => "hello.png", width => 50, wrap => 'l')
20              
21             Constructor. Accepts three options: C, C, as a
22             integer in percent, and C, as a string denoting the position.
23             C is mandatory.
24              
25             These arguments are saved in the objects and can be accessed with:
26             =cut
27              
28             =back
29              
30             =head1 METHODS
31              
32             =over 4
33              
34             =item filename
35              
36             =item rotate
37              
38             Allowed values are 90 180 270. Rotation happens around the image
39             figure and before the scaling.
40              
41             =item width
42              
43             =item wrap
44              
45             If 'l', the float will wrap on the left, if 'r' will wrap on the
46             right, if 'f' it's not floating, but it's intended as fullpage (will
47             insert a clearpage after the image). This is handy if there is some
48             long series of images without text.
49              
50             =item fmt
51              
52             =item desc
53              
54             Please note that we concatenate the caption as is. It's up to the
55             caller to pass an escaped string.
56              
57             =cut
58              
59             sub new {
60 442     442 1 3655 my $class = shift;
61 442         1176 my $self = {
62             width => 1,
63             wrap => 0,
64             };
65 442         1621 my %opts = @_;
66              
67 442 50       1008 if (my $f = $opts{filename}) {
68 442         780 $self->{filename} = $f;
69             # just to be sure
70 442 100       1891 unless ($f =~ m{^[0-9A-Za-z][0-9A-Za-z/-]+\.(png|jpe?g)}s) {
71 2         23 die "Illegal filename $f!";
72             }
73             }
74             else {
75 0         0 die "Missing filename argument!";
76             }
77              
78 440 100       1087 if (my $wrap = $opts{wrap}) {
79 309 50 100     1620 if ($wrap eq 'l' or $wrap eq 'r' or $wrap eq 'f') {
      66        
80 309         599 $self->{wrap} = $wrap;
81             }
82             else {
83 0         0 die "Wrong wrapping option";
84             }
85 309 100 100     1006 if ($wrap eq 'l' or $wrap eq 'r') {
86 70   100     198 $opts{width} ||= 50;
87             }
88             }
89              
90 440 100       912 if (my $w = $opts{width}) {
91 87 100       314 if ($w =~ m/^[0-9]+$/s) {
92 86         1029 $self->{width} = sprintf('%.2f', $w / 100);
93             }
94             else {
95 1         11 die "Wrong width $w passed!";
96             }
97             }
98 439 100       959 if (my $r = $opts{rotate}) {
99 37         97 my %angles = (90 => 90, 180 => 180, 270 => 270);
100 37   50     134 $self->{rotate} = $angles{$r} || 0;
101             }
102 439         780 foreach my $k (qw/desc fmt/) {
103 878 100 66     2454 if (exists $opts{$k} and defined $opts{$k}) {
104 432         975 $self->{$k} = $opts{$k};
105             }
106             }
107              
108 439         2612 bless $self, $class;
109             }
110              
111             sub rotate {
112 458     458 1 1010 return shift->{rotate};
113             }
114              
115             sub width {
116 556     556 1 1186 return shift->{width};
117             }
118              
119             sub wrap {
120 447     447 1 835 return shift->{wrap};
121             }
122              
123             sub filename {
124 859     859 1 1915 return shift->{filename};
125             }
126              
127             sub fmt {
128 629     629 1 1322 return shift->{fmt};
129             }
130              
131             sub desc {
132 539     539 1 911 my ($self, @args) = @_;
133 539 100       1103 if (@args) {
134 100         221 $self->{desc} = shift(@args);
135             }
136 539         912 return shift->{desc};
137             }
138              
139             =back
140              
141             =head2 Formatters
142              
143             =over 4
144              
145             =item width_html
146              
147             Width in percent
148              
149             =item width_latex
150              
151             Width as '0.25\textwidth'
152              
153             =cut
154              
155             sub width_html {
156 51     51 1 78 my $self = shift;
157 51         98 my $width = $self->width;
158 51         220 my $width_in_pc = sprintf('%d', $width * 100);
159 51         172 return $width_in_pc . '%';
160             }
161              
162             sub width_latex {
163 229     229 1 298 my $self = shift;
164 229         410 my $width = $self->width;
165 229 100       529 if ($width == 1) {
166 179         347 return "\\textwidth";
167             }
168             else {
169 50         97 return $self->width . "\\textwidth"; # a float
170             }
171             }
172              
173             =item as_latex
174              
175             The LaTeX code for the image. Right and left floats uses the
176             wrapfigure packages. To full page floats a \clearpage is appended.
177              
178             =item as_html
179              
180             The HTML code for the image. Classes used:
181              
182             img.embedimg {
183             margin: 1em;
184             }
185              
186             div.image, div.float_image_f {
187             margin: 1em;
188             text-align: center;
189             padding: 3px;
190             background-color: white;
191             }
192              
193             div.float_image_r {
194             float: right;
195             }
196              
197             div.float_image_l {
198             float: left;
199             }
200              
201             div.float_image_f {
202             clear: both;
203             margin-left: auto;
204             margin-right: auto;
205             }
206              
207              
208             =item output
209              
210             Given that we know the format, just return the right one, using
211             C or C.
212              
213             =back
214              
215              
216             =cut
217              
218              
219              
220             sub as_latex {
221 221     221 1 307 my $self = shift;
222 221         436 my $wrap = $self->wrap;
223 221         429 my $width = $self->width_latex;
224 221         367 my $desc = "";
225 221         401 my $realdesc = $self->desc;
226 221 100 66     653 if (defined($realdesc) && length($realdesc)) {
227             # the \noindent here is harmless if you still want the label,
228             # commenting out the \renewcommand*
229 52         162 $desc = "\n\\caption[]{\\noindent $realdesc}";
230             }
231 221         371 my $src = $self->filename;
232 221         342 my $open;
233             my $close;
234 221 100 100     842 if ($wrap eq 'r' or $wrap eq 'l') {
    100          
235 36         109 $open = "\\begin{wrapfigure}{$wrap}{$width}";
236 36         68 $close = "\\end{wrapfigure}";
237             }
238             elsif ($wrap eq 'f') {
239 119         185 $open = "\\begin{figure}[p]";
240 119         179 $close = "\\end{figure}\n\\clearpage";
241             }
242             else {
243 66         112 $open = "\\begin{figure}[htbp!]";
244 66         91 $close = "\\end{figure}";
245             }
246 221 100       411 my $rotation = $self->rotate ? "origin=c,angle=" . $self->rotate . ',' : '';
247 221 100       413 my $heightratio = $desc ? '0.85' : "";
248 221         1105 my $out = <<"EOF";
249              
250             $open
251             \\centering
252             \\includegraphics[${rotation}keepaspectratio=true,height=$heightratio\\textheight,width=$width]{$src}$desc
253             $close
254             EOF
255 221         1079 return $out;
256             }
257              
258             sub as_html {
259 218     218 1 317 my $self = shift;
260 218         384 my $wrap = $self->wrap;
261 218         318 my $width = "";
262 218         264 my $desc;
263 218         289 my $class = "image";
264 218         254 my $out;
265 218 100       431 if ($wrap) {
266 154         282 $class = "float_image_$wrap";
267             }
268              
269 218         323 my $src = $self->filename;
270 218         413 my $realdesc = $self->desc;
271 218 100 66     673 if (defined($realdesc) && length($realdesc)) {
272 51         147 $desc = <<"EOF";
273            
$realdesc
274             EOF
275             }
276              
277 218         270 my @styles;
278 218 100       386 if ($self->width != 1) {
279 43         103 push @styles, "width:" . $self->width_html . ";";
280             }
281 218 100       449 if (my $rotate = $self->rotate) {
282 19         58 push @styles, "transform:rotate(${rotate}deg);";
283 19         28 push @styles, "background: transparent;";
284             }
285 218         311 my $style_html = "";
286 218 100       438 if (@styles) {
287 55         149 $style_html = q{ style="} . join(' ', @styles) . q{"};
288             }
289 218         844 $out = qq{\n
\n} .
290             qq{$src\n};
291 218 100       444 if (defined $desc) {
292 51         95 $out .= $desc;
293             }
294 218         332 $out .= "\n";
295 218         936 return $out;
296             }
297              
298             sub output {
299 420     420 1 592 my $self = shift;
300 420 100       710 if ($self->fmt eq 'ltx') {
    50          
301 211         427 return $self->as_latex;
302             }
303             elsif ($self->fmt eq 'html') {
304 209         353 return $self->as_html;
305             }
306             else {
307 0           die "Bad format ". $self->fmt;
308             }
309             }
310              
311             1;
312