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 45     45   69770 use strict;
  45         100  
  45         3034  
3 45     45   566 use warnings;
  45         114  
  45         1107  
4 45     45   259 use utf8;
  45         85  
  45         274  
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 2649 my $class = shift;
61 442         1369 my $self = {
62             width => 1,
63             wrap => 0,
64             };
65 442         1980 my %opts = @_;
66              
67 442 50       1164 if (my $f = $opts{filename}) {
68 442         895 $self->{filename} = $f;
69             # just to be sure
70 442 100       2097 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       1305 if (my $wrap = $opts{wrap}) {
79 309 50 100     1893 if ($wrap eq 'l' or $wrap eq 'r' or $wrap eq 'f') {
      66        
80 309         690 $self->{wrap} = $wrap;
81             }
82             else {
83 0         0 die "Wrong wrapping option";
84             }
85 309 100 100     1229 if ($wrap eq 'l' or $wrap eq 'r') {
86 70   100     234 $opts{width} ||= 50;
87             }
88             }
89              
90 440 100       1012 if (my $w = $opts{width}) {
91 87 100       351 if ($w =~ m/^[0-9]+$/s) {
92 86         1021 $self->{width} = sprintf('%.2f', $w / 100);
93             }
94             else {
95 1         10 die "Wrong width $w passed!";
96             }
97             }
98 439 100       1059 if (my $r = $opts{rotate}) {
99 37         119 my %angles = (90 => 90, 180 => 180, 270 => 270);
100 37   50     155 $self->{rotate} = $angles{$r} || 0;
101             }
102 439         929 foreach my $k (qw/desc fmt/) {
103 878 100 66     2783 if (exists $opts{$k} and defined $opts{$k}) {
104 432         1109 $self->{$k} = $opts{$k};
105             }
106             }
107              
108 439         3267 bless $self, $class;
109             }
110              
111             sub rotate {
112 458     458 1 1134 return shift->{rotate};
113             }
114              
115             sub width {
116 556     556 1 1470 return shift->{width};
117             }
118              
119             sub wrap {
120 447     447 1 968 return shift->{wrap};
121             }
122              
123             sub filename {
124 859     859 1 2239 return shift->{filename};
125             }
126              
127             sub fmt {
128 629     629 1 1647 return shift->{fmt};
129             }
130              
131             sub desc {
132 539     539 1 1061 my ($self, @args) = @_;
133 539 100       1287 if (@args) {
134 100         261 $self->{desc} = shift(@args);
135             }
136 539         1255 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 97 my $self = shift;
157 51         106 my $width = $self->width;
158 51         242 my $width_in_pc = sprintf('%d', $width * 100);
159 51         197 return $width_in_pc . '%';
160             }
161              
162             sub width_latex {
163 229     229 1 337 my $self = shift;
164 229         480 my $width = $self->width;
165 229 100       578 if ($width == 1) {
166 179         401 return "\\textwidth";
167             }
168             else {
169 50         107 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 358 my $self = shift;
222 221         472 my $wrap = $self->wrap;
223 221         490 my $width = $self->width_latex;
224 221         420 my $desc = "";
225 221         498 my $realdesc = $self->desc;
226 221 100 66     762 if (defined($realdesc) && length($realdesc)) {
227             # the \noindent here is harmless if you still want the label,
228             # commenting out the \renewcommand*
229 52         189 $desc = "\n\\caption[]{\\noindent $realdesc}";
230             }
231 221         474 my $src = $self->filename;
232 221         428 my $open;
233             my $close;
234 221 100 100     1005 if ($wrap eq 'r' or $wrap eq 'l') {
    100          
235 36         118 $open = "\\begin{wrapfigure}{$wrap}{$width}";
236 36         84 $close = "\\end{wrapfigure}";
237             }
238             elsif ($wrap eq 'f') {
239 119         225 $open = "\\begin{figure}[p]";
240 119         206 $close = "\\end{figure}\n\\clearpage";
241             }
242             else {
243 66         194 $open = "\\begin{figure}[htbp!]";
244 66         121 $close = "\\end{figure}";
245             }
246 221 100       473 my $rotation = $self->rotate ? "origin=c,angle=" . $self->rotate . ',' : '';
247 221 100       487 my $heightratio = $desc ? '0.85' : "";
248 221         1215 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         1236 return $out;
256             }
257              
258             sub as_html {
259 218     218 1 334 my $self = shift;
260 218         466 my $wrap = $self->wrap;
261 218         378 my $width = "";
262 218         307 my $desc;
263 218         375 my $class = "image";
264 218         360 my $out;
265 218 100       521 if ($wrap) {
266 154         335 $class = "float_image_$wrap";
267             }
268              
269 218         392 my $src = $self->filename;
270 218         470 my $realdesc = $self->desc;
271 218 100 66     773 if (defined($realdesc) && length($realdesc)) {
272 51         198 $desc = <<"EOF";
273            
$realdesc
274             EOF
275             }
276              
277 218         332 my @styles;
278 218 100       528 if ($self->width != 1) {
279 43         115 push @styles, "width:" . $self->width_html . ";";
280             }
281 218 100       465 if (my $rotate = $self->rotate) {
282 19         56 push @styles, "transform:rotate(${rotate}deg);";
283 19         34 push @styles, "background: transparent;";
284             }
285 218         358 my $style_html = "";
286 218 100       469 if (@styles) {
287 55         214 $style_html = q{ style="} . join(' ', @styles) . q{"};
288             }
289 218         980 $out = qq{\n
\n} .
290             qq{$src\n};
291 218 100       579 if (defined $desc) {
292 51         138 $out .= $desc;
293             }
294 218         388 $out .= "\n";
295 218         1154 return $out;
296             }
297              
298             sub output {
299 420     420 1 803 my $self = shift;
300 420 100       804 if ($self->fmt eq 'ltx') {
    50          
301 211         488 return $self->as_latex;
302             }
303             elsif ($self->fmt eq 'html') {
304 209         490 return $self->as_html;
305             }
306             else {
307 0           die "Bad format ". $self->fmt;
308             }
309             }
310              
311             1;
312