File Coverage

blib/lib/Image/Base/SVGout.pm
Criterion Covered Total %
statement 24 114 21.0
branch 4 56 7.1
condition 0 36 0.0
subroutine 8 21 38.1
pod 9 9 100.0
total 45 236 19.0


line stmt bran cond sub pod time code
1             # Copyright 2011, 2012 Kevin Ryde
2              
3             # This file is part of Image-Base-Other.
4             #
5             # Image-Base-Other is free software; you can redistribute it and/or modify
6             # it under the terms of the GNU General Public License as published by the
7             # Free Software Foundation; either version 3, or (at your option) any later
8             # version.
9             #
10             # Image-Base-Other is distributed in the hope that it will be useful, but
11             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13             # for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Image-Base-Other. If not, see .
17              
18              
19             package Image::Base::SVGout;
20 2     2   13081 use 5.006;
  2         10  
  2         89  
21 2     2   11 use strict;
  2         4  
  2         72  
22 2     2   12 use Carp;
  2         4  
  2         263  
23 2     2   12 use vars '$VERSION', '@ISA';
  2         4  
  2         206  
24              
25 2     2   5139 use Image::Base;
  2         9590  
  2         3425  
26             @ISA = ('Image::Base');
27              
28             $VERSION = 9;
29              
30             # uncomment this to run the ### lines
31             #use Devel::Comments '###';
32              
33             sub new {
34 4     4 1 353 my ($class, %params) = @_;
35              
36 4 50       13 if (ref $class) {
37 0         0 my $self = $class;
38 0         0 $class = ref $self;
39 0 0       0 if ($self->{'-filehandle'}) {
40 0         0 croak "Cannot clone SVGout after drawing begun";
41             }
42 0         0 %params = (%$self, %params); # inherit
43             ### copy params: \%params
44             }
45              
46 4 50       13 if (defined $params{'-file'}) {
47 0         0 croak "Cannot load initial -file, Image::Base::SVGout is output-only";
48             }
49 4         15 return bless \%params, $class;
50             }
51              
52             sub DESTROY {
53 4     4   447 my ($self) = @_;
54 4 50       130 if ($self->{'-filehandle'}) {
55 0         0 $self->save; # closing
56             }
57             }
58              
59             sub set {
60 1     1 1 8 my ($self, %param) = @_;
61 1 50       4 if ($self->{'-filehandle'}) {
62 0         0 foreach my $key ('-file', '-title', '-description') {
63 0 0       0 if (exists $param{$key}) {
64 0         0 _nochange_str ($self, $key, $param{$key});
65             }
66             }
67 0         0 foreach my $key ('-width', '-height') {
68 0 0       0 if (exists $param{$key}) {
69 0         0 _nochange_str ($self, $key, $param{$key});
70             }
71             }
72             }
73 1         6 %$self = (%$self, %param);
74             }
75             sub _nochange_str {
76 0     0     my ($self, $key, $newval) = @_;
77 0 0 0       if (defined $self->{$key}
      0        
78             && (! defined $newval
79             || $newval ne $self->{$key})) {
80 0           croak "Cannot change $key after output has begun";
81             }
82             }
83             sub _nochange_num {
84 0     0     my ($self, $key, $newval) = @_;
85 0 0 0       if (defined $self->{$key}
      0        
86             && (! defined $newval
87             || $newval != $self->{$key})) {
88 0           croak "Cannot change $key after output has begun";
89             }
90             }
91              
92             sub _out {
93 0     0     my $self = shift;
94 0   0       my $fh = $self->{'-filehandle'} || _start_out($self);
95 0 0         print $fh @_, "\n"
96             or croak "Error writing $self->{'-file'}: $!";
97             }
98              
99              
100              
101             # require Fcntl;
102             # sysopen FH, $filename, Fcntl::O_WRONLY() | Fcntl::O_TRUNC() | Fcntl::O_CREAT()
103             # or croak "Cannot create $filename: $!";
104             #
105             # if (! $self->save_fh (\*FH)) {
106             # my $err = "Error writing $filename: $!";
107             # { local $!; close FH; }
108             # croak $err;
109             # }
110             # close FH
111             # or croak "Error closing $filename: $!";
112              
113             sub _start_out {
114 0     0     my ($self) = @_;
115              
116 0 0         if ($self->{'save_done'}) {
117 0           croak "Cannot draw more after save()";
118             }
119              
120 0           my $filename = $self->{'-file'};
121 0 0         if (! defined $filename) {
122 0           croak "No -file set";
123             }
124              
125 0           my $width = $self->{'-width'};
126 0           my $height = $self->{'-height'};
127 0 0 0       if (! defined $width || ! defined $height) {
128 0           croak "No -width / -height set";
129             }
130              
131 0           my $class = ref $self;
132 0           my $version = $self->VERSION;
133              
134 0           foreach ($width,$height,$class,$version) {
135 0           $_ = _entitize($_);
136             }
137              
138 0           my ($title, $description);
139 0 0         open my $fh, '>', $filename
140             or croak "Cannot write file $filename: $!";
141              
142 0 0         print $fh <<"HERE",
    0          
    0          
143            
144            
145            
146            
147             HERE
148              
149             (defined ($title = $self->{'-title'})
150             ? ("", _entitize($title), "\n")
151             : ()),
152              
153             (defined ($description = $self->{'-description'})
154             ? ("", _entitize($self->{'-description'}), "")
155             : ())
156              
157             or croak "Error writing $filename: $!";
158              
159 0           return ($self->{'-filehandle'} = $fh);
160             }
161              
162             sub _close_out {
163 0     0     my ($self) = @_;
164              
165 0 0         if (my $fh = delete $self->{'-filehandle'}) {
166 0 0         close $fh or croak "Error closing $self->{'-file'}: $!";
167             }
168             }
169              
170             sub save {
171 0     0 1   my ($self, $filename) = @_;
172             ### Image-Base-SVGout save(): @_
173 0 0         if (@_ > 1) {
174 0           $self->set('-file', $filename);
175             } else {
176 0           $filename = $self->get('-file');
177             }
178             ### $filename
179              
180 0           _out ($self, "");
181 0           $self->{'save_done'} = 1;
182 0           _close_out ($self);
183             }
184              
185             sub xy {
186 0     0 1   my ($self, $x, $y, $colour) = @_;
187             ### Image-Base-SVGout xy(): @_[1 .. $#_]
188              
189 0 0         if (@_ == 3) {
190 0           return undef; # no fetch
191             } else {
192 0           _out ($self,
193             ' 194             '" y="', $y,
195             '" width="1" height="1" fill="', _entitize($colour), '"/>');
196             }
197             }
198              
199             sub rectangle {
200 0     0 1   my ($self, $x1,$y1, $x2,$y2, $colour, $fill) = @_;
201             ### Image-Base-SVGout rectangle(): @_[1 .. $#_]
202              
203 0   0       $fill ||= ($x1 == $x2 || $y1 == $y2); # 1xN or Nx1 done filled
      0        
204 0 0         if (! $fill) {
205 0           $x1 += .5; # for stroke width 1
206 0           $y1 += .5;
207 0           $x2 -= .5;
208 0           $y2 -= .5;
209             }
210 0 0         _out ($self,
211             ' 212             '" y="', $y1,
213             '" width="', $x2-$x1+1,
214             '" height="', $y2-$y1+1, '" ',
215             ($fill?'fill':'stroke'), '="', _entitize($colour),
216             '"/>');
217             }
218              
219             sub ellipse {
220 0     0 1   my ($self, $x1,$y1, $x2,$y2, $colour, $fill) = @_;
221             ### Image-Base-SVGout rectangle(): @_[1 .. $#_]
222              
223 0   0       $fill ||= ($x1 == $x2 || $y1 == $y2); # 1xN or Nx1 done filled
      0        
224 0           my $rx = ($x2-$x1+1) / 2;
225 0           my $ry = ($y2-$y1+1) / 2;
226 0 0         if (! $fill) {
227 0           $rx -= .5; # for stroke width 1
228 0           $ry -= .5;
229             }
230 0 0         _out ($self,
231             ' 232             '" cy="', (($y1+$y2+1) / 2),
233             '" rx="', $rx,
234             '" ry="', $ry,'" ',
235             ($fill?'fill':'stroke'),'="', _entitize($colour), '"/>');
236             }
237              
238             sub line {
239 0     0 1   my ($self, $x1,$y1, $x2,$y2, $colour, $fill) = @_;
240             ### Image-Base-SVGout rectangle(): @_[1 .. $#_]
241              
242 0           _out ($self,
243             ' 244             '" y1="', $y1+.5,
245             '" x2="', $x2+.5,
246             '" y2="', $y2+.5,
247             '" stroke="', _entitize($colour),
248             '" stroke-linecap="square"/>');
249             }
250              
251             sub diamond {
252 0     0 1   my ($self, $x1,$y1, $x2,$y2, $colour, $fill) = @_;
253             ### Image-Base-SVGout diamond(): @_[1 .. $#_]
254              
255 0   0       $fill ||= ($x1 == $x2 || $y1 == $y2); # 1xN or Nx1 done filled
      0        
256 0 0         if ($fill) {
257 0           $x2++;
258 0           $y2++;
259             } else {
260 0           $x1 += .5; # for stroke width 1
261 0           $y1 += .5;
262 0           $x2 += .5;
263 0           $y2 += .5;
264             }
265 0           my $xm = ($x1+$x2)/2;
266 0           my $ym = ($y1+$y2)/2;
267 0 0         _out ($self,
268             ' 269             $xm,',',$y1,' ',
270             $x1,',',$ym,' ',
271             $xm,',',$y2,' ',
272             $x2,',',$ym,'" ',
273             ($fill?'fill':'stroke'),'="', _entitize($colour), '"/>');
274             }
275              
276             sub load {
277 0     0 1   my ($self, $filename) = @_;
278 0           croak "Image::Base::SVGout is output-only";
279             }
280              
281             # Could leave wide chars as utf8 bytes, and latin1 bytes upgraded, if apply
282             # the right layers to the open and in new enough perl. For now send all
283             # non-ascii-printable to numbered.
284             #
285             my %entity = ('&' => '&',
286             '"' => '"',
287             '<' => '<',
288             '>' => '>',
289             );
290             sub _entitize {
291 0     0     my ($value) = @_;
292 0           $value =~ s{([&"<>]|[^\t\r\n\x20-\x7F])}
293 0 0         { $entity{$1} || ('&#'.ord($1).';') }eg;
294 0           return $value;
295             }
296              
297             1;
298             __END__